99 votes

Déplacer les décimales dans un double

Donc, j'ai un double set égal à 1234, je veux déplacer une décimale sur 12,34

Donc, pour ce faire, je multiplie .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 affichera le résultat "12.340000000000002"

Existe-t-il un moyen, sans simplement le formater à deux décimales, d’avoir le double magasin 12.34 correctement?

190voto

Peter Lawrey Points 229686

Si vous utilisez double ou float, vous devez utiliser l'arrondissement ou de s'attendre à voir des erreurs d'arrondi. Si vous ne pouvez pas faire cela, utilisez BigDecimal.

Le problème que vous avez est que de 0,1 n'est pas une représentation exacte, et en effectuant le calcul deux fois, vous êtes aggravé son erreur.

Cependant, à 100 peuvent être représentés avec précision, alors essayez de:

double x = 1234;
x /= 100;
System.out.println(x);

qui affiche:

12.34

Cela fonctionne parce qu' Double.toString(d) effectue une petite quantité de l'arrondissement sur votre nom, mais il n'est pas beaucoup. Si vous vous demandez à quoi ça pourrait ressembler, sans arrondi:

System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));

impressions:

0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375

En bref, l'arrondi est inévitable pour des réponses intelligentes à virgule flottante de savoir si vous faites cela de manière explicite ou non.


Remarque: x / 100 et x * 0.01 ne sont pas exactement les mêmes quand il s'agit de l'erreur d'arrondi. C'est parce que le tour d'erreur pour la première expression dépend des valeurs de x, alors que l' 0.01 dans le second, un fixe ronde erreur.

for(int i=0;i<200;i++) {
    double d1 = (double) i / 100;
    double d2 = i * 0.01;
    if (d1 != d2)
        System.out.println(d1 + " != "+d2);
}

imprime

0.35 != 0.35000000000000003
0.41 != 0.41000000000000003
0.47 != 0.47000000000000003
0.57 != 0.5700000000000001
0.69 != 0.6900000000000001
0.7 != 0.7000000000000001
0.82 != 0.8200000000000001
0.83 != 0.8300000000000001
0.94 != 0.9400000000000001
0.95 != 0.9500000000000001
1.13 != 1.1300000000000001
1.14 != 1.1400000000000001
1.15 != 1.1500000000000001
1.38 != 1.3800000000000001
1.39 != 1.3900000000000001
1.4 != 1.4000000000000001
1.63 != 1.6300000000000001
1.64 != 1.6400000000000001
1.65 != 1.6500000000000001
1.66 != 1.6600000000000001
1.88 != 1.8800000000000001
1.89 != 1.8900000000000001
1.9 != 1.9000000000000001
1.91 != 1.9100000000000001

52voto

Jon Skeet Points 692016

Non - si vous souhaitez stocker les valeurs décimales avec précision, utilisez BigDecimal . double ne peut tout simplement pas représenter un nombre tel que 0,1 exactement, pas plus que vous ne pouvez écrire la valeur d'un tiers avec un nombre fini de chiffres décimaux.

46voto

Augusto Points 14531

s'il ne s'agit que de formater, essayez printf

     double x = 1234;
    for(int i=1;i<=2;i++)
    {
      x = x*.1;
    }
    System.out.printf("%.2f",x);
 

sortie

 12.34
 

30voto

Dans le logiciel financier, il est courant d'utiliser des entiers pour de la monnaie. À l'école, on nous a enseigné comment utiliser point fixe, au lieu de flotter, mais c'est généralement des puissances de deux. Le stockage de pièces en nombres entiers qui pourrait être appelé "point fixe".

int i=1234;
printf("%d.%02d\r\n",i/100,i%100);

En classe, il nous a été demandé, en général, ce nombre peut être représentée exactement dans une base.

Pour base=p1^n1*p2^n2... on peut représenter n'importe quel N, où N=n*p1^m1*p2^m2.

Laissez - base=14=2^1*7^1... vous pouvez représenter 1/7 1/14 1/28 1/49 mais pas 1/3

Je sais au sujet de logiciel financier -- j'ai converti Les rapports financiers de VAX asm à PASCAL. Ils avaient leur propre formatln() avec les codes pour de la monnaie. La raison de la conversion a été de 32 bits entiers n'étaient plus assez. +/- 2 milliards de centimes est de $20 millions de dollars et qui a débordé pour la Coupe du Monde ou les jeux Olympiques, j'ai oublié.

J'ai été prêté serment de garder le secret. Oh bien. Dans academea, si c'est bien vous publiez; dans l'industrie, vous pouvez le garder secret.

12voto

Angel Koh Points 697

vous pouvez essayer la représentation d'un nombre entier

 int i =1234;
int q = i /100;
int r = i % 100;

System.out.printf("%d.%d",q, r);
 

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