2010-11-16 12 views
1

La discussion à this answer vient de me faire penser à l'égalité et à l'équivalence des nombres à virgule flottante. Je suis conscient que les nombres à virgule flottante ne peuvent pas toujours être représentés avec précision. La question est, y at-il des expressions mathématiquement équivalentes qui donneront des résultats différents en utilisant l'arithmétique à virgule flottante? Pouvez vous donner un exemple?Des expressions équivalentes peuvent-elles donner des résultats différents?

Modifier: Laissez-moi être plus clair. Je suis conscient que le même code avec différents compilateurs ou machines différentes peut retourner des résultats différents. Ce que je cherche, ce sont deux expressions mathématiquement équivalentes que je peux comparer dans mon interpréteur Python/programme C++/Whatever et obtenir un résultat inattendu.

Répondre

3

sont là mathématiquement équivalentes expressions qui produiront différents résultats lors de l'utilisation en virgule flottante arithmétique?

Absolument. En fait, vous devriez vous attendre à ce que cela arrive plus souvent qu'autrement.

Même le même code can yield different results sur différentes machines ou compilateurs.

Pouvez-vous donner un exemple?

Bien sûr. Ce code Java devrait donner de façon répétée deux résultats différents:

public strictfp class Test { 
    public static void main(String[] args) throws Exception { 
     float a = 0.7f; 
     float b = 0.3f; 
     float c = 0.1f; 

     float r1 = ((a * b) * c); 
     float r2 = (a * (b * c)); 

     System.out.println(r1); 
     System.out.println(r2); 
    } 
} 
2

Oui, comparez par ex.

x = (a * b)/c; 

avec

x = a * (b/c); 

Voici un exemple en C qui démontre ceci:

#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    double a, b, c, x1, x2; 

    a = sqrt((double)rand()); 
    b = sqrt((double)rand()); 
    c = sqrt((double)rand()); 

    x1 = (a * b)/c; 
    x2 = a * (b/c); 

    printf("a = %.20f\n", a); 
    printf("b = %.20f\n", b); 
    printf("c = %.20f\n", c); 
    printf("x1 = %.20f\n", x1); 
    printf("x2 = %.20f\n", x2); 
    printf("x1 - x2 = %.20f\n", x1 - x2); 

    return 0; 
} 

Pour moi, cela donne les résultats suivants:

$ gcc -O3 -Wall math.c -o math 
$ ./math 
a = 129.64181424216494065149 
b = 16807.00000000000000000000 
c = 40282.13093916457728482783 
x1 = 54.09073256970189902404 
x2 = 54.09073256970190612947 
x1 - x2 = -0.00000000000000710543 
$ 

(Core i7, gcc 4.0.1, Mac OS X 10.6)

Notez que, en général, vous pouvez obtenir des résultats différents avec une expression donnée et différent CPU, compilateur, commutateurs de compilateur, bibliothèque de mathématiques, etc.

0

Je vais essayer avec la multiplication et l'addition:

en pseudo Code -c

float x = 1/7; 
float y = x * 4; 
float z = x + x + x + x; 
if (y != z) { 
    printf("oh noes!\n"); 
} 
+0

Avez-vous réellement essayé cela? –

+0

Non, et cela ne fonctionnerait probablement que sur un compilateur avec un indicateur d'optimisation particulier. –

Questions connexes