我有两段代码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
所以我想了解这可能是什么原因?
答案 0 :(得分:3)
您可以参考public BigDecimal(double val)
的Java文档:
public BigDecimal(double val)
将double转换为BigDecimal 这是double的二进制的精确十进制表示 浮点值。返回的BigDecimal的比例是 最小值,使得(10 ^ scale×val)是一个整数。
这个构造函数的结果可能有些不可预测。一 可能会假设在Java中编写新的BigDecimal(0.1)会创建一个 BigDecimal正好等于0.1(未缩放的值为1,带有 比例为1),但它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为double(或者为此) 重要的是,作为任何有限长度的二进制分数)。因此,价值 传入构造函数的不完全等于 0.1,尽管有外观。
另一方面,String构造函数是完全可预测的:编写新的BigDecimal(“0.1”)创建 正如人们所期望的那样,BigDecimal正好等于0.1。 因此,通常建议使用String构造函数 优先使用这一个。
必须使用double作为源 对于BigDecimal,请注意此构造函数提供了精确的 转换;它没有给出与转换double相同的结果 使用Double.toString(double)方法然后使用 BigDecimal(String)构造函数。要获得该结果,请使用静态 valueOf(double)方法。
答案 1 :(得分:2)
字符串"1.240472701"
是十进制值的文本表示。 BigDecimal
代码会对此进行解析,并使用字符串中表示的完全值创建BigDecimal
。
但是double
1.240472701
只是该精确十进制值的(近似)近似值。 Double
无法准确表示所有十进制值,因此存储在double
中的确切值略有不同。如果您将其传递给BigDecimal
,则需要使用不同的值并将其转换为精确的BigDecimal
。但是BigDecimal
只有不精确的double
,它不知道确切的文本表示。因此它只能表示double
中的值,而不是源文本的值。
在第一种情况下:
String --> BigDecimal
因为BigDecimal是 make 来精确表示十进制值,所以转换是准确的。
在第二种情况下:
1 2
Source code text --> double --> BigDecimal
在第二种情况下,第一次转换(1)中的精度会丢失。第二个转换(2)是精确的,但输入 - 双 - 是源代码文本1.240472701
的不精确表示(实际上,它是1.2404727010000000664291519569815136492252349853515625
)。
所以:永远不会使用双初始化BigDecimal,如果可以避免的话。改为使用字符串。
这就是为什么第一个BigDecimal是精确的而第二个不是。
答案 2 :(得分:1)
由于用户 thegauravmahawar 提供了文档的答案。是的,这是因为 BigDecimal 案例中的缩放。
所以值可能看起来等于你,但内部java在存储BigDecimal类型的值时使用Scaling。
原因:缩放。
改进:
你可以在你要比较的数字上调用setScale: 像这样
new BigDecimal ("7.773").setScale(2).equals(new BigDecimal("7.774").setScale (2))
这样可以避免犯错。