Pourquoi Java J'ai essayé Eclipse & Intellij, mais ils ne montrent aucun avertissement. p> code d'échantillon: P> + = code> a un mauvais résultat et comment puis-je empêcher ce problème? (Par exemple, toutes les voies indiquent avertissement code> dans l'IDE?) {
long a = 20000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 20000000000000088 NG
}
{
long a = 10000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 10000000000000090 OK
}
{
long a = 20000000000000000L;
double b = 90.0;
a += (long) b;
System.out.println(a); // 20000000000000090 OK
}
3 Réponses :
Selon les JLS, ceci expression d'affectation des composés est équivalente à p> car La valeur Votre deuxième extrait produit Votre troisième extrait est équivalent à p> qui utilise Entier Arithmétique . Je ne connais pas d'outils pour vous avertir à ce sujet. P> Related: p> b code> est un double code>, Promotion numérique binaire se produit avant que l'addition ne se produise. Les deux opérandes sont convertis en valeurs code> double code> et l'addition se produit avec une arithmétique à virgule flottante. P> 2000000000000000090 code> ne peut pas être représenté exactement comme un double code> et donc vous perdez la précision, obtenez 20000000000000088 code> à la place. Il est ensuite reconjecté à un long code> qui a suffisamment de précision pour représenter 20000000000000088 code>. P> 10000000000000090 code> qui Peut être représenté exactement comme un double code>. p> 2000000000000000090 code> peut être représenté sous la forme d'un long code>. p>
Java utilise Numéros de points flottants IEEE 64 bits , qui utilisent 53 chiffres binaires pour représenter la important. Dans le premier exemple, ici la variable Dans cet exemple, il est possible de représenter A code> est converti en double qui doit utiliser un exposant supérieur à 1 pour le représenter, et ce ne sera plus Une représentation exacte de la valeur 2000000000000000000L. P> A code> en utilisant uniquement le signification et un exposant de 1. P> {
long a = 20000000000000000L;
double b = 90.0;
a += (long) b;
System.out.println(a); // 20000000000000090 OK
}
Comme tout le programmeur (comme moi) peut comprendre pour empêcher tout Je viens de grep tout IDE montre des erreurs tout en tapant non correspondant lorsque + = code> Codage manquant, j'ai trouvé un moyen simple: il suffit d'interdire tout + = code> comme règle de codage. P>
+ = code> dans mes projets et modifiez A + = b code> à A = A + B code>. P >
+ code>, comme ci-dessous: p>
@Sotirios Cette question n'explique pas pourquoi un nombre sans partie fractionnée n'aurait ce comportement.
@ 4castle La précision de
double code> ne s'applique pas uniquement à sa partie fractionnée.@Sotiriosdelimanolis qui est l'information exacte que la question ne contient pas. Cette réponse Même Recommande i> Structure des chiffres à des nombres entiers car "L'arithmétique entier dans le point flottant est exact".
Lecture requise i> b>: Que faut-il savoir que chaque informatique devrait connaître sur l'arithmétique de points flottants
@Sotiriosdelimanolis Je ne pense pas que la question est en double. Il peut expliquer pourquoi
0,1 + 0,2 = 0,30000000000000004 code> mais pas1000000000000000000 + 90 = 10000000000000088 code>C'est la même question de précision. Essayez
system.out.println (20000000000000090D); code> et vous verrez la même chose. Laissez-moi essayer de trouver un meilleur duplicata.@Sotiriosdelimanolis et cette réponse ne veut pas expliquer
Comment puis-je empêcher ce problème? (Par exemple, n'importe quand montre l'avertissement dans l'IDE?) code>Bon, je vais rouvrirai.
@andyf La raison de ces deux comportements est la même.
0.1 code> ne peut pas être représenté exactement dans le point flottant. Ni ne peut1000000000000000090 code>. La mantissa n'a pas assez de bits. Je suppose que vous pourriez affirmer que dans le cas de0,1 code>, il ne pourrait jamais y avoir suffisamment de bits, mais dans le second cas, l'ajout de bits résoudrait le problème. Tous les bits ajoutent sont déplacer i> le problème. Il est toujours là avec des nombres de grandeur et de précision assez grande.Cette question se pose encore et encore. C'est un duplicata, peut-être pas exactement un dup de la question référencée par @sotiriosdelimanolis, mais un DUP néanmoins. Je savoir i> C'est un dup d'une réponse que j'ai écrit il y a quelques années ... je vais y trouver.
@JimGarrison Merci pour votre référence. Je pense que pour la plupart des codeurs, ils ont juste besoin d'un outil (IDE, etc.) pour leur dire que cela ne codant pas comme ça. J'ai essayé Eclipse & Intellij mais les deux ne montrent aucun avertissement.
@andyf Les IDes supposent que vous comprenez le point flottant, tout comme s'ils s'attendent à ce que vous compreniez que le débordement entier est ignoré silencieusement. Les numéros de points flottants sont une idée puissante, mais ils agissent assez différemment de notre "intuition" qu'ils doivent être étudiés et compris pour ce qu'ils sont.
@JimGarrison merci pour votre réponse. Mais, comme tous les programmeurs (comme moi) ne peuvent toujours pas remarquer ce problème, j'ai trouvé un moyen simple: juste interdire
+ = code> comme règle de codage. Voir ma réponse.C'est tout simplement idiot. Cela n'a rien à voir avec
+ = code> et tout pour faire avec le fait que le point flottant a une précision limitée. Vous aurez le même problème si vous écriveza = A + B code> à la place.@JimGarrison mais l'IDE me montrera l'erreur de compilée lorsque
a = A + B code>.