J'ai donc un double ensemble égal à 1234, je veux déplacer une décimale pour en faire 12,34
Donc, pour ce faire, je multiplie 0,1 à 1234 deux fois, un peu comme ça
double x = 1234;
for(int i=1;i<=2;i++)
{
x = x*.1;
}
System.out.println(x);
Cela imprimera le résultat, "12.340000000000002"
Existe-t-il un moyen, sans simplement le mettre en forme à deux décimales, pour que le double stocke correctement 12,34?
x /= 100;
?Réponses:
Si vous utilisez
double
oufloat
, vous devez utiliser l'arrondi ou vous attendre à voir des erreurs d'arrondi. Si vous ne pouvez pas faire cela, utilisezBigDecimal
.Le problème que vous avez est que 0,1 n'est pas une représentation exacte, et en effectuant le calcul deux fois, vous ajoutez cette erreur.
Cependant, 100 peuvent être représentés avec précision, alors essayez:
qui imprime:
Cela fonctionne car
Double.toString(d)
effectue un petit nombre d'arrondis en votre nom, mais ce n'est pas beaucoup. Si vous vous demandez à quoi cela pourrait ressembler sans arrondir:imprime:
En bref, l'arrondi est inévitable pour les réponses sensées en virgule flottante, que vous le fassiez explicitement ou non.
Remarque:
x / 100
etx * 0.01
ne sont pas exactement les mêmes en matière d'erreur d'arrondi. En effet, l'erreur d'arrondi pour la première expression dépend des valeurs de x, tandis que0.01
dans la seconde a une erreur d'arrondi fixe.impressions
la source
1234/100
, comme vous l'avez fait, ne fait vraiment rien sur le problème sous-jacent - elle devrait être exactement égale à l'écriture1234 * 0.01
./100
et*0.01
sont équivalents les uns aux autres, mais pas aux OP*0.1*0.1
.Non - si vous souhaitez stocker les valeurs décimales avec précision, utilisez
BigDecimal
. ne peutdouble
tout simplement pas représenter exactement un nombre comme 0,1, pas plus que vous ne pouvez écrire la valeur d'un tiers exactement avec un nombre fini de chiffres décimaux.la source
si c'est juste un formatage, essayez printf
production
la source
System.out.printf()
la bonne voie à suivre.Dans les logiciels financiers, il est courant d'utiliser des entiers pour quelques centimes. À l'école, on nous a appris à utiliser la virgule fixe au lieu du flottant, mais il s'agit généralement de puissances de deux. Le stockage de quelques centimes en nombres entiers peut également être appelé "virgule fixe".
En classe, on nous a demandé en général quels nombres peuvent être exactement représentés dans une base.
Pour
base=p1^n1*p2^n2
... vous pouvez représenter n'importe quel N où N = n * p1 ^ m1 * p2 ^ m2.Soit
base=14=2^1*7^1
... vous pouvez représenter 1/7 1/14 1/28 1/49 mais pas 1/3Je connais les logiciels financiers - j'ai converti les rapports financiers de Ticketmaster de VAX asm à PASCAL. Ils avaient leur propre formatln () avec des codes pour quelques centimes. La raison de la conversion était que les entiers 32 bits ne suffisaient plus. +/- 2 milliards de centimes, c'est 20 millions de dollars et cela a débordé pour la Coupe du monde ou les Jeux olympiques, j'ai oublié.
J'ai juré de garder le secret. Tant pis. Dans l'académie, si c'est bon, vous publiez; dans l'industrie, vous le gardez secret.
la source
vous pouvez essayer la représentation par nombre entier
la source
r
est inférieur à 10, aucun remplissage de 0 ne se produit et 1204 produirait un résultat de 12,4. La chaîne de mise en forme correcte est plus similaire à "% d.% 02d"Cela est dû à la façon dont les ordinateurs stockent les nombres à virgule flottante. Ils ne le font pas exactement. En tant que programmeur, vous devriez lire ce guide en virgule flottante pour vous familiariser avec les épreuves et les tribulations de la gestion des nombres à virgule flottante.
la source
C'est drôle que de nombreux articles mentionnent l'utilisation de BigDecimal mais que personne ne se soucie de donner la bonne réponse basée sur BigDecimal? Parce que même avec BigDecimal, vous pouvez toujours vous tromper, comme le montre ce code
Donne cette sortie
Le constructeur BigDecimal mentionne spécifiquement qu'il est préférable d'utiliser le constructeur String qu'un constructeur numérique. La précision ultime est également influencée par le MathContext facultatif.
Selon le BigDecimal Javadoc, il est possible de créer un BigDecimal qui est exactement égal à 0,1, à condition d'utiliser le constructeur String.
la source
Oui il y a. Avec chaque opération double, vous risquez de perdre de la précision, mais le degré de précision diffère pour chaque opération et peut être minimisé en choisissant la bonne séquence d'opérations. Par exemple, lors de la multiplication d'un ensemble de nombres, il est préférable de trier l'ensemble par exposant avant de multiplier.
Tout livre décent sur le calcul des nombres le décrit. Par exemple: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Et pour répondre à votre question:
Utilisez diviser au lieu de multiplier, de cette façon vous obtenez un résultat correct.
la source
Non, car les types à virgule flottante Java (en fait tous les types à virgule flottante) sont un compromis entre taille et précision. Bien qu'ils soient très utiles pour de nombreuses tâches, si vous avez besoin d'une précision arbitraire, vous devez utiliser
BigDecimal
.la source