2017-08-13 3 views
1

Je cherchais un moyen précis de multiplier deux nombres à virgule flottante en Java, et j'ai lu que je devrais utiliser BigDecimal, mais cela ne fonctionne pas comme prévu. Qu'est-ce que je fais mal?Multipliez précisément deux nombres en Java

Mon code:

BigDecimal a = new BigDecimal(3.53); 
BigDecimal b = new BigDecimal(3.59); 
BigDecimal c = a.multiply(b); 

System.out.println(c); 

Résultat:

12.672699999999998796873512674210388041622697702955394242845497954075284496866515837609767913818359375 

Résultat attendu:

12.6727 
+4

Vous devriez essayer d'imprimer 'a' et' b'. –

+1

Je vois c'est le même résultat, le résultat attendu est une valeur arrondie pour la valeur ci-dessus, vous pouvez utiliser quelque chose comme ** Math.round ** –

+0

Au début, les constantes flottantes ne sont pas précisées. Doit comprendre profondément. –

Répondre

12

Lorsque vous utilisez un constructeur BigDecimal(double) il ne peut pas être plus précis qu'un double, utilisez la String formulaire à la place. Comme,

BigDecimal a = new BigDecimal("3.53"); 
BigDecimal b = new BigDecimal("3.59"); 
BigDecimal c = a.multiply(b); 
System.out.println(c); 

qui délivre en sortie

12.6727 

Le Javadoc lié dit en partie -

Notes:

  1. Les résultats de ce constructeur peuvent être quelque peu imprévisible. On pourrait supposer qu'écrire BigDecimal(0.1) nouveau en Java crée un BigDecimal qui est exactement égal à 0,1 (une valeur non mise à l'échelle de 1, avec une échelle de 1), mais il est en fait égal à 0.1000000000000000055511151231257827021181583404541015625. C'est parce que 0,1 ne peut pas être représenté exactement comme double (ou, en fait, comme une fraction binaire de toute longueur finie). Ainsi, la valeur transmise au constructeur n'est pas exactement égale à 0,1, malgré les apparences.

  2. Le constructeur String, d'autre part, est tout à fait prévisible: l'écriture new BigDecimal("0.1") crée un BigDecimal qui est exactement égal à 0,1, comme on pouvait s'y attendre. Par conséquent, il est généralement recommandé d'utiliser le String constructor de préférence à celui-ci.

+0

Comment utiliser "BigDecimal a = BigDecimal. valueOf (3.53d); " ? De cette façon, je peux utiliser une double variable réelle au lieu de la convertir en chaîne, et toujours conserver la précision – Mikemike

+0

@Mikemike c'est toujours une mauvaise idée. L'utilisation de doubles à la première place est le problème. Utilisez String et BigDecimal sans jamais toucher les doubles entre les deux. Si vous utilisez cette approche avec un nombre trop précis pour doubler, vous obtiendrez toujours des résultats erronés. –

+0

@ Louis Wasserman D'une certaine manière, j'ai obtenu de bons résultats: BigDecimal a = BigDecimal.valueOf (3.53d); BigDecimal b = BigDecimal.valueOf (3.59d); BigDecimal c = a.multiplié (b); \t \t System.out.println (c); // 12.6727 – Mikemike