Java Double变量有奇怪的值

alk*_*lkz 2 java double division

可能重复:
浮点运算不能在Java中生成精确结果

我正在做这个简单的划分,但我得到一个非常奇怪的输出:

double a = 60/(1.2-1.1);
Run Code Online (Sandbox Code Playgroud)

a => 600.0000000000008

什么时候应该是600.

提前致谢

ken*_*ytm 9

在IEEE-754二进制双精度中,我们需要考虑二进制表示中的1.1和1.2:

1.2 = 0b1.001100110011001100110011001100110011001100110011001100110011...
1.1 = 0b1.000110011001100110011001100110011001100110011001100110011001...
Run Code Online (Sandbox Code Playgroud)

请注意,我们需要无限多位来完全用二进制表示它们.double只有53位的意义,我们必须砍掉这些数字:

1.2 = 0b1.001100110011001100110011001100110011001100110011001100110011...
1.1 = 0b1.000110011001100110011001100110011001100110011001100110011001...
                                                              ^ round from here
==>
1.2 ~ 0b1.0011001100110011001100110011001100110011001100110011
      (= exactly 1.1999999999999999555910790149937383830547332763671875)
1.1 ~ 0b1.0001100110011001100110011001100110011001100110011010
      (= exactly 1.100000000000000088817841970012523233890533447265625)
Run Code Online (Sandbox Code Playgroud)

因此1.2 - 1.1是:

  1.2 ~ 0b1.0011001100110011001100110011001100110011001100110011
- 1.1 ~ 0b1.0001100110011001100110011001100110011001100110011010
————————————————————————————————————————————————————————————————
        0b0.00011001100110011001100110011001100110011001100110010000
        (= exactly 0.09999999999999986677323704498121514916419982910156250000)
Run Code Online (Sandbox Code Playgroud)

我们实际上可以精确计算60/0.0999999999999998667732370449812151491641998291015625,这给出了

600.0000000000007993605777301137740672368493927467455286920109359612256820927...
                ^ 16th significant figure
Run Code Online (Sandbox Code Playgroud)

这符合OP的结果

600.0000000000008
Run Code Online (Sandbox Code Playgroud)


Kal*_*see 5

因为double基元是浮点数据类型,其交换精度以保持更大范围的值.

如果你需要任意精度,你应该使用BigDecimal.