Вопрос
Правильно, я думаю, что я действительно живу мечтой. У меня есть следующий кусок кода, который я компилируемый и запущен на машине AIX:
AIX 3 5
PowerPC_POWER5 processor type
IBM XL C/C++ for AIX, V10.1
Version: 10.01.0000.0003
#include <stdio.h>
#include <math.h>
#define RADIAN(x) ((x) * acos(0.0) / 90.0)
double nearest_distance(double radius,double lon1, double lat1, double lon2, double lat2){
double rlat1=RADIAN(lat1);
double rlat2=RADIAN(lat2);
double rlon1=lon1;
double rlon2=lon2;
double a=0,b=0,c=0;
a = sin(rlat1)*sin(rlat2)+ cos(rlat1)*cos(rlat2)*cos(rlon2-rlon1);
printf("%lf\n",a);
if (a > 1) {
printf("aaaaaaaaaaaaaaaa\n");
}
b = acos(a);
c = radius * b;
return radius*(acos(sin(rlat1)*sin(rlat2)+
cos(rlat1)*cos(rlat2)*cos(rlon2-rlon1)));
}
int main(int argc, char** argv) {
nearest_distance(6367.47,10,64,10,64);
return 0;
}
Теперь значение «A» после расчета сообщается как «1». И, на этом машине AIX, он выглядит как 1> 1, верно, как мой «если» введен !!! И мои акусы того, что я думаю, это «1» возврат NANQ с 1 больше 1. Могу ли я спросить, как это даже возможно? Я не знаю, что больше думать!
Код работает нормально в других архитектурах, где «A» действительно принимает ценность того, что я думаю, 1 и ACOS (A) 0.
Решение
Если вы делаете сравнение, где результат и EXPCTEDEDRESULT являются типы поплавок:
if (result == expectedResult)
Тогда маловероятно, что сравнение будет правдой. Если сравнение верно, то, вероятно, нестабильно - крошечные изменения в входных значениях, компиляторе или процессоре могут изменить результат и сделать сравнение false.
Сравнение с Epsilon - абсолютная ошибка
if (fabs(result - expectedResult) < 0.00001)
От Сравнение номеров плавающих точек
Какой ученый компьютер должен знать о арифметике с плавающей точкой
Другие советы
Распечатайте биты. Возможно, вы просто одурачены некоторой ошибкой округления на дисплее плавающихся как десятичных действительных чисел.
То Printf. Функция без указанной точности будет отображаться только первые 6 цифр. Итак, попробуйте печать с более высокой степенью точности ... Возможно, что A немного больше 1, но только немного. Если вы хотите сделать вещи более надежными, вместо (A> 1) вы можете использовать (A-1)> Epsilon для некоторого значения epsilon.
1.00000000000000000000001 больше 1. Вы уверены, что вы просто не видите достаточно десятичных знаков? Если этот чек проходит, я бы парил, что ваша проблема.
Обычное решение - использовать некоторую форму EPSILON, чтобы остановить беспокоиться о ошибках округления. т.е. если удвоенный, который вы должны быть, то попробуйте сделать
if ( a > 1.00001f )
Это, вероятно, достаточно близко к одному, чтобы не причинить вам проблемы :)