为什么new BigDecimal("0.015").compareTo(new BigDecimal(0.015))返回-1?如果我希望这两者相等,是否有另一种方法来比较它们?
Rei*_*eus 20
由于浮点运算的不精确性,它们并不完全相等
System.out.println(new BigDecimal(0.015));
Run Code Online (Sandbox Code Playgroud)
显示器
0.01499999999999999944488848768742172978818416595458984375
Run Code Online (Sandbox Code Playgroud)
为了扩展@Reimeus 的答案,BigDecimal的各种构造函数接受不同类型的输入.所述浮点构造,采取一个浮点作为输入,并由于漂浮的方式的限制/双打被存储,这些只能存储准确是2的幂的值.
因此,例如,可以精确地表示2 -2或0.25.0.875是(2 -1 + 2 -2 + 2 -3),因此它也可以准确地表示.只要数量可以用幂的总和来表示,其中上限和下限相差不超过53,那么数字可以精确地表示.绝大多数数字都不符合这种模式!
特别地,0.15不是2的幂,也不是2的幂的和,因此表示不准确.
另一方面,字符串构造函数通过在内部使用不同的格式来存储数字,从而准确地存储它.因此,当你比较两者时,他们会比较不同.
A double无法准确表示该值0.015.它在64位二进制位中可以表示的最接近的值是0.01499999999999999944488848768742172978818416595458984375.构造函数new BigDecimal(double)旨在保留double参数的精确值,这绝不是完全正确的0.015.因此,你的比较结果.
但是,如果您显示该double值,例如:
System.out.println(0.01499999999999999944488848768742172978818416595458984375);
Run Code Online (Sandbox Code Playgroud)
它输出0.015- 暗示了一种解决方法.将a转换double为a会String选择所需的最短十进制表示,以区别于其他可能的double值.
因此,如果您BigDecimal从double's String表示创建一个,它将具有更多的值,如您所期望的那样.这种比较是正确的:
new BigDecimal(Double.toString(0.015)).equals(new BigDecimal("0.015"))
Run Code Online (Sandbox Code Playgroud)
实际上,该方法BigDecimal.valueOf(double)正是出于此目的,因此您可以将上述内容缩短为:
BigDecimal.valueOf(0.015).equals(new BigDecimal("0.015"))
Run Code Online (Sandbox Code Playgroud)
new BigDecimal(double)仅当您的目的是保留参数的精确二进制值时,才应使用构造函数.否则,打电话BigDecimal.valueOf(double),其文件说:
这通常是将
double(或float)转换为a 的首选方式BigDecimal.
或者,String如果可以的话,使用a 并double完全避免细微之处.