Когда это правда? - PullRequest
       14

Когда это правда?

2 голосов
/ 30 апреля 2010

Да, я думаю, что действительно живу мечтой. У меня есть следующий фрагмент кода, который я компилирую и запускаю на машине 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.

Ответы [ 4 ]

8 голосов
/ 30 апреля 2010

Если вы делаете сравнение, где result и expctedResult являются типами с плавающей запятой:

if (result == expectedResult)

Тогда вряд ли сравнение будет верным. Если сравнение верно, то оно, вероятно, нестабильно - незначительные изменения во входных значениях, компиляторе или ЦП могут изменить результат и сделать сравнение ложным.

Сравнение с эпсилоном - абсолютная ошибка

if (fabs(result - expectedResult) < 0.00001)

С Сравнение чисел с плавающей запятой


Что должен знать каждый компьютерщик об арифметике с плавающей точкой

4 голосов
/ 30 апреля 2010

Функция printf без указанной точности покажет вам только первые 6 цифр. Итак, попробуйте печатать с более высокой степенью точности ... возможно, что значение a немного больше 1, но только немного. Если вы хотите сделать вещи более надежными, вместо (a> 1) вы можете использовать (a-1)> epsilon для некоторого значения epsilon.

4 голосов
/ 30 апреля 2010

Распечатайте биты. Возможно, вас просто одурачивает ошибка округления при отображении чисел с плавающей запятой в виде десятичных вещественных чисел.

1 голос
/ 30 апреля 2010

1.000000000000000000001 больше 1. Вы уверены, что просто не видите достаточно десятичных знаков? Если эта проверка пройдена, я бы поставил на это вашу проблему.

Обычное решение - использовать некую форму эпсилона, чтобы не беспокоиться об ошибках округления. то есть, если вы должны быть удвоены, попробуйте сделать

if ( a > 1.00001f )

Это, вероятно, достаточно близко к одному, чтобы не вызывать у вас проблемы:)

...