Java Double variables have strange values [duplica

2019-05-24 13:36发布

问题:

Possible Duplicate:
Floating point arithmetic not producing exact results in Java

I was doing this simple division but I get a very strange output:

double a = 60/(1.2-1.1);

a => 600.0000000000008

When it should be 600.

thanks in advance

回答1:

In IEEE-754 binary double, we need to consider 1.1 and 1.2 in the binary representation:

1.2 = 0b1.001100110011001100110011001100110011001100110011001100110011...
1.1 = 0b1.000110011001100110011001100110011001100110011001100110011001...

note that we need infinitely many bits to represent them exactly in binary. double only has 53 bits of significance, we have to chop off the numbers:

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)

Hence 1.2 - 1.1 is:

  1.2 ~ 0b1.0011001100110011001100110011001100110011001100110011
- 1.1 ~ 0b1.0001100110011001100110011001100110011001100110011010
————————————————————————————————————————————————————————————————
        0b0.00011001100110011001100110011001100110011001100110010000
        (= exactly 0.09999999999999986677323704498121514916419982910156250000)

We can actually compute 60 / 0.0999999999999998667732370449812151491641998291015625 exactly, which gives

600.0000000000007993605777301137740672368493927467455286920109359612256820927...
                ^ 16th significant figure

that matches OP's result of

600.0000000000008


回答2:

Because the double primitive is a floating point data type which trades precision for the ability to hold a larger range of values.

If you need arbitrary precision you should be using BigDecimal instead.



回答3:

You've discovered the wonders of floating point arithmetic. Since the internal representation of a number is in binary, certain decimal numbers can't be represented precisely. As a result, some arithmetic operations will give unexpected results in the least significant digits.

This is covered in exhausting detail in, for example, numerical methods courses, but the Wikipedia article isn't bad.



回答4:

You probably should read "What Every Computer Scientist Should Know About Floating-Point Arithmetic".

In short, not all real values can be represented exactly with a double, so they should be avoided when exact answers are required.



回答5:

You should use BigDecimal to get correct result.



回答6:

This is not precisely a "rounding issue." Certain numbers cannot be exactly represented in binary floating point. Just like 1/3 cannot be represented exactly in decimal, since nobody has an infinite supply of paper. (or bits).