2010-04-30 29 views
2

Bon, je pense que je vis vraiment un rêve. Je le morceau suivant de code qui je compiler et exécuter sur une machine AIX:Quand est> un vrai?

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; 
} 

Maintenant, la valeur de « a » après le calcul est rapporté comme étant « 1 ». Et, sur cette machine AIX, il semble que 1> 1 soit vrai car mon 'si' est entré !!! Et mon acos de ce que je pense être '1' renvoie NanQ puisque 1 est plus grand que 1. Puis-je demander comment c'est possible? Je ne sais plus quoi penser !

Le code fonctionne très bien sur d'autres architectures où « a » prend vraiment la valeur de ce que je pense est 1 et ACOS (a) est 0.

+1

Je préfère utiliser RADIAN (x) (((x) * M_PI)/2), vous appelez la fonction, qui est inutile et plus lente. – nothrow

+1

pour répondre à votre question, 'a> a' ne devrait jamais être vrai, mais si un ressemble à 1, vous pourriez avoir' a> 1', donc vous devez corriger votre question parce que le titre est trompeur, vous n'êtes pas en train de comparer un à lui-même. –

+1

Vous avez tous magnifiquement raison, merci! Je suis confus car le code fonctionne sur différentes architectures/compilateurs. Sur AIX 'a' finit par avoir une valeur comme '1.00000000000000022204'. Je suppose que je dois maintenant mettre en œuvre la comparaison epsilon. – Cricri

Répondre

8

Si vous faites une comparaison où résultat et expctedResult sont les types de flotteur:

if (result == expectedResult) 

il est peu probable que la comparaison sera vrai. Si la comparaison est vraie, elle est probablement instable - de minuscules changements dans les valeurs d'entrée, le compilateur ou le processeur peuvent changer le résultat et rendre la comparaison fausse.

comparaison avec epsilon - erreur absolue

if (fabs(result - expectedResult) < 0.00001) 

De Comparing floating point numbers


What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

+1 Grande référence – Juliano

4

Imprimez les bits. Vous pourriez juste être trompé par une erreur d'arrondi dans l'affichage des flottants en tant que nombres réels décimaux.

1

1.000000000000000000001 est supérieur à 1. Êtes-vous sûr de ne pas voir suffisamment de décimales? Si ce chèque est en train de passer, je parierais que c'est votre problème.

La solution habituelle consiste à utiliser une forme d'epsilon pour éviter les problèmes d'arrondi. à savoir si la double vous devez être ensuite essayer de faire

if (a > 1.00001f) 

Son probablement assez près d'un pour ne pas vous causer des problèmes :)

4

La fonction printf, sans précision spécifiée, montrera uniquement vous les 6 premiers chiffres. Donc, essayez d'imprimer avec un degré de précision plus élevé ... il est possible que a soit légèrement plus grand que 1, mais seulement un peu. Si vous voulez rendre les choses plus robustes, au lieu de (a> 1), vous pouvez utiliser (a-1)> epsilon pour une certaine valeur d'epsilon.