BigDecimal行为的差异

时间:2017-01-11 06:25:12

标签: java bigdecimal

我有两段代码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

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

3 个答案:

答案 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))

这样可以避免犯错。