它是如何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() 方法,但是这种预期的后果?

我也意识到 BigDecimaldoubleValue() 等等,但该图书馆是我的工作与有益的使用 toString() 我不能改变:-(

欢呼声。

有帮助吗?

解决方案

好了, API 不解决这一明显不一致的构造 BigDecimal(double val):

  1. 结果该构造可以有些不可预测。一个可能 假定编写新的 BigDecimal(0.1)在Java创建一个 BigDecimal这是完全相等, 0.1(一个无标值1的比例为1),但它实际上是平等的 要 0.1000000000000000055511151231257827021181583404541015625.这是因为0.1 不可能是 表示完全作为一个双人 (或者, 对于这个问题,因为二分 任何有限的长度)。因此,值 正在通过在的 构造就是不完全等于 0.1,尽管出现.

  2. 串构造,另一方面,是完全可预测的:编写新的BigDecimal("0.1")创建 一个BigDecimal这是完全相等, 0.1,作为一个希望。因此, 它的一般建议 串构造以用于 优先这一个。

  3. 当双必须作为一个资源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仅示出了结果,以几个小数位。

与二进制数的类型(即doublefloat)表示的级分不能被正确地存储在那些类型。

    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)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top