2017-09-29 7 views
0

Quelle est la précision de la comparaison double/flottante (opérateur relationnel) avec types entiers?Quelle est la précision de la comparaison double/flottante (opérateur de relation) avec des types entiers?

Je comprends qu'il n'est pas recommandé d'utiliser le point flottant dans les comparaisons. Mais jusqu'à présent que cette opération est autorisée, voici la question:

int x = 90; 
    float y = 90.00_001f; 

    if (x < y) { 
     System.out.println("it works!"); // gets printed 
    } 

    // now just add one zero to lessen the precision a bit... 

    int x = 90; 
    float y = 90.000_001f; 

    if (x < y) { 
     System.out.println("it works!"); // not printed 
    } 
+1

La précision est la précision comme ce serait avec deux variables 'float', c'est une [conversion d'élargissement] (https://docs.oracle.com/javase/specs/jls/se8/html/jls- 5.html # jls-5.1.2). –

+0

https://stackoverflow.com/questions/13297207/is-it-valid-to-compare-a-double-with-an-int-in-java –

+0

https://stackoverflow.com/questions/41653576/is -it-safe-to-compare-a-float-et-un-int-en-java –

Répondre

0

La précision d'un point flottant simple précision IEEE 754 est comprise entre 6 et 9 chiffres décimaux significatifs (source). Pour double-precision, vous obtenez entre 15 et 17 chiffres décimaux significatifs.

3

Le problème ici est pas la comparaison en entier, mais avec la précision de float lui-même.

Vous pouvez spécifier autant de positions décimales que vous le souhaitez lorsque vous spécifiez un littéral float (ou double); mais cela ne signifie pas que la précision sera conservée lors de la compilation du code.

Par exemple, toutes les conditions suivantes ont la même valeur:

90.f 
90.000_001f 
90.000000000000000000000000000000000000000000000000000000000‌​00000001f 

Ideone demo

donc la raison pour laquelle la deuxième est que la comparaison ne 90.000_001f est égal à 90.f; et c'est égal à la valeur de l'élargissement 90 à float.

0

Les autres réponses sont correctes, donc je ne les répéterai pas ici.

Ce que je veux ajouter une autre surprise potentielle sur les considérer == comme une relation d'équivalence, ce qui implique normalement l'associativité:

(a == b) and (b == c) => (a == c) 

Mais si vous essayez cet extrait par exemple dans https://repl.it:

class Main { 
    public static void main(String[] args) { 
    int i=16777217; 
    float f=16777216.0f; 
    double d=16777216.0; 
    if(i == f) { 
     System.out.println("i == f"); 
    } 
    if(d == f) { 
     System.out.println("d == f"); 
    } 
    if(i == d) { 
     System.out.println("i == d"); 
    } 
    } 
} 

La surprise est que i==f et f==d mais not(i==d) ...
en effet, lors de l'écriture i==f, un conversion implicite float(i)==f arrive, et cette conversion potentiellement perdre la précision, car un int peut exiger jusqu'à 31 bits de précision, tandis qu'un flotteur offre au plus 24.

Cela aurait pu être différent, si vous regardez comment Lisp, Scheme ou récente Squeak/Smalltalk Pharo gère les comparaisons, vous verrez qu'ils se soucient de l'exactitude ...

Extrait de http://www.lispworks.com/documentation/lcl50/aug/aug-170.html

En général, lorsqu'une opération implique à la fois rationnel et un argument à virgule flottante, le nombre rationnel est d'abord converti en format à virgule flottante, puis l'opération est pe rformé. Ce processus de conversion est appelé contagion en virgule flottante. Cependant, pour les comparaisons d'égalité numérique, les arguments sont comparés en utilisant l'arithmétique rationnelle pour assurer la transitivité de la relation d'égalité (ou d'inégalité).