-2

I was calculating a product of two double numbers:106.785 and 217.000 using java as shown below:

    double dd=106.785*217.000;
    System.out.println(dd);

The output that i get is: 23172.344999999998

But when i calculated this using a calculator i get the following result: 23172.345 I tried to go through IEEE 754 docs and everything on double and floating point variables but could not get the correct explanation to this. Can anybody please help me out. Any good explanations will do thank you in advance

Ingo
  • 36,037
  • 5
  • 53
  • 100
  • 2
    Obligatory: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm – Jeroen Vannevel Oct 17 '13 at 15:25
  • 3
    All floating point math has some precision errors. For all intents and purposes 0.344999999999999 is 0.345 – AndyG Oct 17 '13 at 15:26
  • If you're off by 0.000000000002, does it really make a difference? If it does, then use [`BigDecimal`](http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html). – arshajii Oct 17 '13 at 15:27
  • 1
    @AndyG: No, that's not the case. The multiplication itself will be fine in this case. It's the conversion from a decimal representation to binary floating point which is the problem. 106.785 can't be exactly represented in binary floating point. – Jon Skeet Oct 17 '13 at 15:28
  • 2
    If your are interested in computer science I have a really great read for you! [What every computer scientist should know about floating-point arithmetic](http://dl.acm.org/citation.cfm?id=103163) – mwhs Oct 17 '13 at 15:29
  • Corrected tag, as this has nothing to do with Java. In fact, you'll get the same result in every language that uses the platforms native doubles. – Ingo Oct 17 '13 at 15:33
  • I am not concerned about precision its just a random issue that came to my knowledge and i wish to understand the cause so that in future such issues can be handled @mwhs I have already read these articles n m not a mathematician or scientist so i hardly understood them – Ashish Sood Oct 18 '13 at 11:34

2 Answers2

3

106.785 is not representable in IEEE-754 64-bit binary floating-point. The nearest representable value is 106.784999999999996589394868351519107818603515625. Using hexadecimal for the significand, this is 1.ab23d70a3d70a16•26. That significand is shown with 53 bits (one before the “.” and 52 after), which are all that are available in the 64-bit format. If one were added to the last bit, the value would be 106.7850000000000108002495835535228252410888671875, which is farther from 106.785.

So, when Java processes 106.785 in your source text, it converts it to the nearest value, 106.784999999999996589394868351519107818603515625.

When this value is multiplied by 217, the result is approximately 23172.34499999999752617.


Every finite IEEE-754 64-bit binary floating-point value has the form M•2e for some integers M and e such that –253 < M < 253 and –1074 ≤ e ≤ 971.

In order to represent a value near 106.785, M is set to 7514326347011850, and e is set to –46. This produces 7514326347011850 •2-46 = 106.784999999999996589394868351519107818603515625. If you add one to M, the value becomes 106.7850000000000108002495835535228252410888671875.

This M is as large as we can make it to represent something near 106.785, because there are only 53 bits for it in the 64-bit format (52 are explicitly stored in the format, and a 53rd is implied by the exponent). So M must be in this range, and it must be an integer. Therefore, we cannot add any smaller increment to M; we are stuck with the choice of either 106.784999999999996589394868351519107818603515625 or 106.7850000000000108002495835535228252410888671875.

Note: In many documents, you will see the form as a separate sign, a significand normally in [1, 2) (but sometimes in [0, 1)), and an exponent. In this form, the significand has 53 bits: an integer bit before a “.”, then a “.”, then 52 fraction bits. The forms are mathematically equivalent, but the integer form is more useful for certain proofs and it is easier to explain that M can change only in units of one in the integer form. In the fraction form, you must understand that the fraction can change only by units of 2–52.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Check out BigDecimal if you're concerned about such precision - but at the cost of performance

robert
  • 4,612
  • 2
  • 29
  • 39
  • I am not concerned about precision its just a random issue that came to my knowledge and i wish to understand the cause so that in future such issues can be handled – Ashish Sood Oct 18 '13 at 11:33