"新BigDecimal(13.3D)"的结果在不精确的"13.3000000000000007105.."?
-
19-08-2019 - |
题
它是如何Java BigDecimal
可这个痛苦的?
Double d = 13.3D;
BigDecimal bd1 = new BigDecimal(d);
BigDecimal bd2 = new BigDecimal(String.valueOf(d));
System.out.println("RESULT 1: "+bd1.toString());
System.out.println("RESULT 2: "+bd2.toString());
RESULT 1: 13.300000000000000710542735760100185871124267578125
RESULT 2: 13.3
是否有任何情况下结果1将需要?我知道,Java1.5改变的 toString()
方法,但是这种预期的后果?
我也意识到 BigDecimal
已 doubleValue()
等等,但该图书馆是我的工作与有益的使用 toString()
我不能改变:-(
欢呼声。
解决方案
好了, API 不解决这一明显不一致的构造 BigDecimal(double val)
:
结果该构造可以有些不可预测。一个可能 假定编写新的 BigDecimal(0.1)在Java创建一个 BigDecimal这是完全相等, 0.1(一个无标值1的比例为1),但它实际上是平等的 要 0.1000000000000000055511151231257827021181583404541015625.这是因为0.1 不可能是 表示完全作为一个双人 (或者, 对于这个问题,因为二分 任何有限的长度)。因此,值 正在通过在的 构造就是不完全等于 0.1,尽管出现.
串构造,另一方面,是完全可预测的:编写新的BigDecimal("0.1")创建 一个BigDecimal这是完全相等, 0.1,作为一个希望。因此, 它的一般建议 串构造以用于 优先这一个。
当双必须作为一个资源BigDecimal, 注意, 这个构造提供了一个确切的 转换;它不会给予相同的 结果转换的双到 字符串中使用的 一倍。toString(double)的方法和 然后使用BigDecimal(String) 构造。得到这一结果, 使用 静态值(double)方法.
道德的故事:痛苦似乎是自己造成的,只是使用 new BigDecimal(String val)
或 BigDecimal.valueOf(double val)
而不是=)
其他提示
您的问题无关与BigDecimal
,一切与Double
,它不能代表13.3准确,因为它使用二进制小数内部。
因此,在第一行引入的误差。第一BigDecimal
简单地保留它,而String.valueOf()
确实使所述第二个具有期望的内容的一些舍入腥,几乎靠运气。
您可能想告知自己如何浮点值实现( IEEE 754-1985 )。突然间,一切都将变得清晰。
这是不BigDecimal
的故障 - 这是double
的故障。 BigDecimal
被准确地表示d
的确切值。 String.valueOf
仅示出了结果,以几个小数位。
与二进制数的类型(即double
,float
)表示的级分不能被正确地存储在那些类型。
Double d = 13.3;
BigDecimal bdNotOk = new BigDecimal(d);
System.out.println("not ok: " + bdNotOk.toString());
BigDecimal bdNotOk2 = new BigDecimal(13.3);
System.out.println("not ok2: " + bdNotOk2.toString());
double x = 13.3;
BigDecimal ok = BigDecimal.valueOf(x);
System.out.println("ok: " + ok.toString());
double y = 13.3;
// pretty lame, constructor's behavior is different from valueOf static method
BigDecimal bdNotOk3 = new BigDecimal(y);
System.out.println("not ok3: " + bdNotOk3.toString());
BigDecimal ok2 = new BigDecimal("13.3");
System.out.println("ok2: " + ok2.toString());
Double e = 0.0;
for(int i = 0; i < 10; ++i) e = e + 0.1; // some fractions cannot be accurately represented with binary
System.out.println("not ok4: " + e.toString()); // should be 1
BigDecimal notOk5 = BigDecimal.valueOf(e);
System.out.println("not ok5: " + notOk5.toString()); // should be 1
/*
* here are some fractions that can be represented exactly in binary:
* 0.5 = 0.1 = 1 / 2
* 0.25 = 0.01 = 1 / 4
* 0.75 = 0.11 = 3 / 4
* 0.125 = 0.001 = 1 / 8
*/
输出:
not ok: 13.300000000000000710542735760100185871124267578125
not ok2: 13.300000000000000710542735760100185871124267578125
ok: 13.3
not ok3: 13.300000000000000710542735760100185871124267578125
ok2: 13.3
not ok4: 0.9999999999999999
not ok5: 0.9999999999999999
只需使用 BigDecimal.valueOf(d)
强>或 new BigDecimal(s)
强>