41 votes

Pourquoi comparer un float à un double incohérent en Java?

 class Test{  
    public static void main(String[] args){  
        float f1=3.2f;  
        float f2=6.5f;  

        if(f1==3.2){
            System.out.println("same");  
        }else{
            System.out.println("different");  
        }
        if(f2==6.5){
            System.out.println("same");  
        }else{  
            System.out.println("different");  
        }
    }  
}  
 

out mis:

 different
same
 

Pourquoi le résultat est comme ça ... Je m'attendais à same comme résultat dans le premier cas

Merci d'avance....

41voto

Abimaran Kugathasan Points 12318

La différence est que de 6,5 peuvent être représentés exactement dans les deux float et double - considérant que le 3.2 ne peuvent pas être représentés exactement dans l'autre type... et les deux plus proches des approximations sont différents. Une comparaison d'égalité entre float et double convertit tout d'abord le flotteur à un double et compare ensuite les deux. Donc, la perte de données.


Vous ne devriez jamais comparer des flotteurs ou double pour l'égalité; car, vous ne pouvez pas vraiment garantir que le nombre que vous attribuez à l'float ou double est exacte.

Serrant un nombre infini de nombres réels en un nombre fini de bits nécessite une évaluation approximative de la représentation. Bien qu'il existe une infinité de nombreuses entiers, dans la plupart des programmes de la suite de entier les calculs peuvent être stockés en 32 bits. En revanche, étant donné un nombre fixe de bits, la plupart des calculs avec des nombres réels produira des quantités qui ne peut pas être exactement représentée à l'aide que le nombre de bits. Par conséquent, l' résultat d'un calcul flottant doit souvent être arrondis afin pour intégrer son sens de la représentation. Cette erreur d'arrondi est l' caractéristique de calcul flottant.

Vérifiez Que Tous les ordinateurs Scientifique Doit Savoir à Propos de l'Arithmétique à virgule Flottante de plus!

25voto

sigpwned Points 2166

Elles sont toutes les deux mises en œuvre de différentes parties de la virgule flottante IEEE standard. Un float est de 4 octets, alors qu'un double est de 8 octets.

En règle générale, vous devriez probablement vous préférez utiliser double dans la plupart des cas, et seulement utiliser float quand vous avez une bonne raison de le faire. (Un exemple d'une bonne raison pour utiliser float , par opposition à un double est: "je sais que je n'ai pas besoin de beaucoup de précision et j'ai besoin de stocker un million d'entre eux dans la mémoire.") Il est également intéressant de mentionner qu'il est difficile de prouver que vous n'avez pas besoin d' double de précision.

Aussi, lorsque l'on compare les valeurs à virgule flottante pour l'égalité, vous serez généralement voulez utiliser quelque chose comme Math.abs(a-b) < EPSILONa et b sont les valeurs à virgule flottante être comparées et EPSILON est une petite valeur à virgule flottante comme 1e-5. La raison pour cela est que les valeurs à virgule flottante rarement coder la valeur exacte qu'ils "devraient" -- ou plutôt, ils ont l'habitude de coder une valeur très proche-de sorte que vous avez à "plisser" lorsque vous déterminer si deux valeurs sont les mêmes.

EDIT: tout le monde devrait lire le lien @Kugathasan Abimaran affiché ci-dessous: Ce que Tout informaticien Devez Savoir à Propos de l'Arithmétique à virgule Flottante de plus!

5voto

Teepeemm Points 1342

Pour voir à quoi vous avez affaire, vous pouvez utiliser les Float et les Double's toHexString méthode:

class Test {
    public static void main(String[] args) {
        System.out.println("3.2F is: "+Float.toHexString(3.2F));
        System.out.println("3.2  is: "+Double.toHexString(3.2));
        System.out.println("6.5F is: "+Float.toHexString(6.5F));
        System.out.println("6.5  is: "+Double.toHexString(6.5));
    }
}
$ java Test
3.2F is: 0x1.99999ap1
3.2  is: 0x1.999999999999ap1
6.5F is: 0x1.ap2
6.5  is: 0x1.ap2

Généralement, un certain nombre a une représentation exacte si elle est égale à A * 2^B, où A et B sont des nombres entiers dont les valeurs autorisées sont définies par la spécification du langage (et le double a plus de valeurs autorisées).

Dans ce cas,
6.5 = 13/2 = (1+10/16)*4 = (1+a/16)*2^2 == 0x1.ap2, tandis que
3.2 = 16/5 = ( 1 + 9/16 + 9/16^2 + 9/16^3 + . . . ) * 2^1 == 0 x 1.999. . . p1.
Mais Java ne peut contenir qu'un nombre fini de chiffres, donc il coupe la .999. . . arrêt à un certain point. (Vous vous souvenez peut de maths que 0.999. . .=1. C'est en base 10. En base 16, il serait de 0.la fff. . .=1.)

3voto

S4beR Points 318
 class Test {  
  public static void main(String[] args) {  
    float f1=3.2f;  
    float f2=6.5f;  

    if(f1==3.2f)  
      System.out.println("same");  
    else  
      System.out.println("different");  

    if(f2==6.5f)  
      System.out.println("same");  
    else  
      System.out.println("different");  
    }  
  }
 

Essayez comme ça et ça va marcher. Sans 'f', vous comparez un type flottant avec un autre type flottant et une précision différente pouvant entraîner des résultats inattendus, comme dans votre cas.

2voto

supercat Points 25534

Il n'est pas possible de comparer les valeurs de type float et double directement. Avant les valeurs peuvent être comparées, il est nécessaire de convertir l' double de float, ou de convertir l' float de double. Si l'on fait le ancien titre de comparaison, la conversion se demander "est ce que la de la float détiennent la meilleure possible float de la représentation de l' double's de la valeur?" Si on fait la conversion de ce dernier, la question sera "l' float détiennent une représentation parfaite de l' doubles'valeur". Dans de nombreux contextes, la première question est la plus significative, mais Java suppose que toutes les comparaisons entre float et double sont destinés à poser la dernière question.

Je voudrais suggérer que, indépendamment de ce qu'est une langue disposés à tolérer, les normes de codage doit absolument positivement interdire de faire des comparaisons directes entre les opérandes de type float et double. Compte tenu de code comme:

float f = function1();
double d = function2();
...
if (d==f) ...

il est impossible de dire ce comportement est prévu dans les cas où l' d représente une valeur qui n'est pas exactement représentable en float. Si l'intention est d' f être converti en double, et le résultat de la conversion en comparaison avec d, on devrait écrire la comparaison comme

if (d==(double)f) ...

Bien que le transtypage ne change pas le comportement du code, il est clair que le code de comportement est intentionnel. Si l'intention était que la comparaison indiquer si f détient le meilleur float de la représentation de l' d, il convient de:

if ((float)d==f)

Notez que le comportement de c'est très différent de ce qui allait se passer sans la fonte. A votre code original cast le double opérande de chaque comparaison float, puis les deux tests d'égalité serait passé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X