繁体   English   中英

BigDecimal行为的差异

[英]Difference in BigDecimal behavior

我有两段代码new BigDecimal("1.240472701")new BigDecimal(1.240472701) 现在,如果我在两种方法上都使用java的compareTo方法,那么我会得到它们不相等的信息。

当我使用java的System.out.println()方法打印值时。 对于这两个值,我得到不同的结果。 例如

new BigDecimal("1.240472701") -> 1.240472701

new BigDecimal(1.240472701) -> 1.2404727010000000664291519569815136492252349853515625

所以我想了解这可能是什么原因?

您可以为此参考public BigDecimal(double val)的Java文档:

public BigDecimal(double val) 

将双精度型转换为BigDecimal,它是双精度型二进制浮点值的精确十进制表示形式。 返回的BigDecimal的小数位数是最小值,使得(10 ^ scale×val)是整数。

  • 此构造函数的结果可能无法预测。 有人可能会假设用Java编写新的BigDecimal(0.1)会创建一个BigDecimal,它精确地等于0.1(未缩放的值1,小数位数为1),但实际上等于0.1000000000000000055511151231257827021181583404541015625。 这是因为0.1无法精确表示为双精度(或就此而言,表示为任何有限长度的二进制分数)。 因此,尽管出现,但是传递给构造函数的值并不完全等于0.1。

  • 另一方面,String构造函数是完全可预测的:就像预期的那样,编写新的BigDecimal(“ 0.1”)会创建一个完全等于0.1的BigDecimal。 因此,通常建议优先使用String构造函数。

  • 当必须将double用作BigDecimal的源时,请注意,此构造函数提供了精确的转换。 它与使用Double.toString(double)方法然后使用BigDecimal(String)构造函数将double转换为String的结果不同。 要获得该结果,请使用静态valueOf(double)方法。

字符串"1.240472701"是十进制值的文本表示形式。 BigDecimal代码对此进行解析,并使用字符串中表示的确切值创建一个BigDecimal

但是, double 1.240472701只是该精确十进制值的(近似值)近似值。 Double不能完全代表所有十进制值,因此存储在double精度中的精确值略有不同。 如果将其传递给BigDecimal ,它将采用不同的值并将其转换为精确的BigDecimal 但是BigDecimal只有不精确的double可以通过,它不知道确切的文本表示形式。 因此,它只能表示double的值,而不能表示源文本中的值。

在第一种情况下:

String --> BigDecimal

因为BigDecimal的准确地表示十进制值,即转换是准确的。

在第二种情况下:

                  1          2
Source code text --> double --> BigDecimal

在第二种情况下,第一次转换(1)会损失精度。 第二次转换(2)是精确的,但输入-两次-是源代码文本1.240472701的不精确表示(实际上是1.2404727010000000664291519569815136492252349853515625 )。

因此:如果可以避免, 切勿使用double初始化BigDecimal 请改用字符串。

这就是为什么第一个BigDecimal是精确的,而第二个则不是。

由于用户thegauravmahawar提供了文档的答案。 是的,这是因为在BigDecimal情况下缩放
因此这些值似乎与您相等,但是在内部,Java在存储BigDecimal类型的值时使用了Scaling。
原因:扩展。

改进:

like this

new BigDecimal ("7.773").setScale(2).equals(new BigDecimal("7.774").setScale (2))

这样可以避免您犯任何错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM