使用BigDecimal将两个数相乘会返回错误的值

Mar*_*ark 32 java math bigdecimal

执行以下代码:

new BigDecimal(0.06 * 3).toString()
Run Code Online (Sandbox Code Playgroud)

返回0.179999999999999993338661852249060757458209991455078125而不是0.18.

执行

new BigDecimal(0.06).multiply(new BigDecimal(3)).toString() 
Run Code Online (Sandbox Code Playgroud)

返回相同的结果.

这怎么可能?

Jon*_*eet 50

你没有使用两个数字相乘BigDecimal.您将它们double与算术相乘,并将结果传递给BigDecimal构造函数.

你要:

new BigDecimal("0.06").multiply(new BigDecimal("3")).toString()
Run Code Online (Sandbox Code Playgroud)

请注意,您确实需要字符串中的值 - 否则您使用的double值为0.06,这不是0.06 ...您在开始之前就丢失了信息.(你真的不需要3的字符串形式,但为了保持一致性,我这样做了.)

例如:

System.out.println(new BigDecimal(0.06));
Run Code Online (Sandbox Code Playgroud)

版画

0.059999999999999997779553950749686919152736663818359375
Run Code Online (Sandbox Code Playgroud)

  • @dotvav:你觉得`BigDecimal.valueOf`在做什么?它也将它转换为字符串:)但是我认为如果你将`double`转换成`BigDecimal`,你很可能会遇到严重的问题,你应该重新审视你的设计. (9认同)
  • @Mark:由于所有正常原因,它并不完全可以表示为"double".考虑一下比特模式是什么 - 就像试图将1/3表示为精确的小数一样. (4认同)
  • 执行`new BigDecimal(0.06).multiply(new BigDecimal(3)).toString()`返回相同的结果 (2认同)
  • @Mark:这是由于一个单独的问题,我将在编辑中解释. (2认同)
  • @JonSkeet使用常量时没关系.但是当生产代码已经用'double`喂你时,我觉得在将它解析成`BigDecimal`之前将它格式化为`String`是一种浪费. (2认同)