2010-03-09 8 views
2

je fais la commande d'impression java ci-dessous pour cette double variable double test = 58.15; Lorsque je fais un System.out.println (test); et System.out.println (nouveau Double (test) .toString()); Il imprime comme 58.15.En ce qui concerne BigDecimal

Quand je fais un System.out.println (nouveau BigDecimal (test)) Je reçois la valeur ci-dessous 58,14999999999999857891452847979962825775146484375

Je suis en mesure de comprendre « test » double valeur variable est enregistrée en interne comme 58,1499999. Mais quand je fais ci-dessous deux System.out.println je reçois la sortie comme 58.15 et non 58.1499999.

System.out.println (test);

System.out.println (nouveau Double (test) .toString());

Il imprime la sortie comme 58.15 pour les deux précédents.

Est-ce que les instructions System.out.println ci-dessus arrondissent la valeur 58.1499999 et l'affichent comme 58.15?

Répondre

5
System.out.println(new BigDecimal("58.15")); 

Pour construire un BigDecimal d'une constante codée en dur, vous devez toujours utiliser l'une des constantes de la classe (ZERO, ONE ou TEN) ou l'un des constructeurs de cordes. La raison en est que si vous mettez la valeur dans un double, vous avez déjà perdu la précision qui ne peut jamais être récupérée.

EDIT: les polygenelubricants ont raison. Plus précisément, vous utilisez Double.toString ou équivalent. Pour citer de là:

Combien de chiffres doit être imprimé pour la partie fractionnaire de m ou? Il doit y avoir au moins un chiffre à représentent la partie décimale, et au-delà que beaucoup, mais seulement comme beaucoup, plus de chiffres que nécessaire pour unique distinguer la valeur d'argument de valeurs adjacentes de type double. Que est, supposons que x est la valeur mathématique exacte représentée par la représentation décimale produite par cette méthode pour un argument non nul fin zéro d. Alors d doit être la valeur double la plus proche de x; ou si deux valeurs doubles sont également près de x, puis d doit être l'un d'entre eux et le moins peu significative du significand de d doit être 0.

+0

Merci beaucoup pour l'info – Arav

3

Oui, println (ou plus précisément, Double.toString) tours. Pour preuve, System.out.println(.1D); imprime 0.1, ce qui est impossible à représenter en binaire.

De même, lors de l'utilisation de BigDecimal, n'utilisez pas le constructeur double, car cela tenterait de représenter précisément une valeur imprécise. Utilisez plutôt le constructeur String.

+0

Je suppose un nouveau test BigDecimal ("52.15") ou double = 52.15; nouveau BigDecimal (nouveau Double (test) .toString()) sont une seule et même chose. SVP corrigez-moi si je me trompe. Ma compréhension est nouvelle Double (double variable) .toString prend la valeur arrondie 58.15 et non 58.149999999. Est-ce qu'il arrondit? Donc, les résultats sont les mêmes si j'utilise de toute façon? – Arav

+1

@arav: Non, ils ne sont pas identiques. Le constructeur de chaîne ne perd pas de précision mais le double l'a déjà perdu. Autrement dit, le double est déjà 58.149999 lorsque vous appelez le constructeur. De plus, il n'effectue aucun arrondi, il utilise les bits bruts pour construire exactement ce que vous lui donnez. –

+0

Oui, 'Double.toString (.1D) .equals (" 0.1 ")', et oui, l'arrondi s'est produit ici. '.1D' n'est pas exactement' 0.1', mais 'Double.toString' s'en rapproche. C'est un genre de scénario "à deux fautes", sur lequel vous ne devriez pas compter. – polygenelubricants

1

out.println et Double.toString() utiliser le format spécifié dans Double.toString(double).

BigDecimal utilise plus de précision par défaut, tel que décrit dans le javadoc, et lorsque vous appelez toString() il sort tous les personnages jusqu'au niveau de précision disponible à une double primitive car .15 ne dispose pas d'une représentation binaire exacte.

+0

Merci beaucoup pour l'info – Arav