Java BigDecimal行为的差异

Java BigDecimal行为的差异,java,bigdecimal,Java,Bigdecimal,我有两段代码newbigdecimal(“1.240472701”)和newbigdecimal(1.240472701)。现在,如果我在这两种方法上使用java的compareTo方法,那么我会发现它们并不相等 当我使用java的System.out.println()方法打印值时。对于这两个值,我得到了不同的结果。比如说 new BigDecimal("1.240472701") -> 1.240472701 new BigDecimal(1.240472701) -> 1.2

我有两段代码
newbigdecimal(“1.240472701”)
newbigdecimal(1.240472701)
。现在,如果我在这两种方法上使用java的compareTo方法,那么我会发现它们并不相等

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

new BigDecimal("1.240472701") -> 1.240472701

new BigDecimal(1.240472701) -> 1.2404727010000000664291519569815136492252349853515625

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

您可以参考的Java文档:

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

  • 此构造函数的结果可能有些不可预测。一个 可能假设在Java中编写新的BigDecimal(0.1)会创建 BigDecimal正好等于0.1(未标度值为1,带 比例为1),但实际上等于 0.1000000000000000055511151231257827021181583404541015625. 这是因为0.1不能精确地表示为double(或者 物质,作为任何有限长度的二元分数)。因此,价值 传递给构造函数的不完全等于 0.1,尽管有外观

  • 另一方面,字符串构造函数是完全可预测的:编写新的BigDecimal(“0.1”)创建 正如人们所期望的,正好等于0.1的大十进制数。 因此,通常建议使用字符串构造函数 用于优先于这个的

  • 当必须将双精度计数器用作源时 对于BigDecimal,请注意此构造函数提供了精确的 转化;它不会给出与转换double相同的结果 使用Double.toString(Double)方法,然后使用 BigDecimal(字符串)构造函数。要获得该结果,请使用静态 (双)值法

因为用户thegauravmahawar从文档中提供了答案。是的,这是因为在BigDecimal的情况下进行了缩放。
因此,这些值可能看起来与您相同,但java内部在存储BigDecimal类型的值时使用缩放。
原因:缩放。

改进:

您可以对正在比较的数字调用setScale: 像这样

new BigDecimal ("7.773").setScale(2).equals(new BigDecimal("7.774").setScale (2))
这将避免您犯任何错误。

字符串
“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.240472701000000066429151956981513649252349853515625

所以:如果可以避免的话,千万不要用double来初始化BigDecimal。改为使用字符串


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

不是每个小数都可以用浮点表示variable@ScaryWombat:我认为与OP有关的是,除了从不同类型创建数字外,还要创建相同的“数字”