为什么打印到控制台时某些双打会自动舍入?

时间:2014-09-28 20:37:02

标签: java double bigdecimal floating-point-precision rounding-error

说我有以下代码:

double factor;
double num = 4.35;
BigDecimal y = new BigDecimal(num);
BigDecimal n = new BigDecimal(factor);
BigDecimal asBigDecimal = y.multiply(n);
double asDouble = num * factor;
System.out.println("Double: " + asDouble + "\tBigDecimal: " + asBigDecimal);

当我将factor设置为以下各项时会发生这种情况:

factor = 1:    Double: 4.35 BigDecimal: 4.3499999999999996447286321199499070644378662109375
factor = 10:   Double: 43.5 BigDecimal: 43.4999999999999964472863211994990706443786621093750
factor = 100:  Double: 434.99999999999994   BigDecimal: 434.9999999999999644728632119949907064437866210937500
factor = 1000: Double: 4350.0   BigDecimal: 4349.9999999999996447286321199499070644378662109375000

此外,当我将System.out.print(4.35 / 10);作为单独的程序运行时,我在控制台中获得0.43499999999999994。为什么乘以1,10和1000会在控制台中给出舍入答案(作为双打)?我理解浮点精度的基础知识,4.35不能完全以二进制形式表示,那么为什么4.35打印到控制台(asDouble)?为什么不乘以100或除以10自动舍入?

1 个答案:

答案 0 :(得分:2)

有几件事正在发生。首先,二进制有舍入,然后有十进制舍入。

查看那些BigDecimal值的二进制表示(我使用了我的Decimal/Binary Converter):

factor = 1:    100.0101100110011001100110011001100110011001100110011         (52 bits)
factor = 10:   101011.011111111111111111111111111111111111111111111111       (53 bits)
factor = 100:  110110010.11111111111111111111111111111111111111111111011     (56 bits)
factor = 1000: 1000011111101.1111111111111111111111111111111111111111100111  (59 bits)

因子1和10的结果不是二进制四舍五入;它们是<= 53位。打印为17位十进制数字,分别为4.35和43.5。

因子100和1000的结果是四舍五入的。因子100结果向下舍入到该值,因为位54是0:

   factor = 100:  110110010.11111111111111111111111111111111111111111111        (53 bits)

以十进制表示,即434.99999999999994315658113919198513031005859375。圆为17位,为434.99999999999994。

因子1000结果被四舍五入到该值,因为位54及以上是> 1/2 ULP:

factor = 1000: 1000011111110

那是4350。