0

When I run the following code:

double x = 4.35;
double y = x * 100;
System.out.println(y);

I get 434.99999999999994 which is expected due to the nature of floating point precision. However when I run:

double x = 4.35;
double y = x * 1000;
System.out.println(y);

I get 4350.0 in the console. Similarly when I replace the 1000 with 10, I get 43.5, which is peculiar, since there is no rounding error for these numbers. It seems that there is only rounding error when I mulptiply the double by 10 to the power of the number of decimal places. Why is it like that?

Also, when I tried running the three blocks of code using 4.25 as my value for x, I got a nice 425.0 in the console. Does rounding error only apply to some decimal values?

EDIT: Dividing 4.35 by 10 also gave me a wacky decimal (0.43499999999999994 to be exact). Also, if I set x to 43.5, there were no rounding errors at all. Multiplying by 10 gave me 435.0.

EDIT 2: I think some people are misinterpreting my question. I'm asking why this happens and not how to avoid running into these errors.

null
  • 2,060
  • 3
  • 23
  • 42
  • Interestingly, when I use a `float`, I get 435.0 instead. – Pokechu22 Sep 28 '14 at 03:36
  • The reason lies in the way the computation is implemented in the particular CPU you are using. http://en.wikipedia.org/wiki/Floating-point_unit – S.D. Sep 28 '14 at 06:44
  • A previous question about, as you say, why this happens rather than how to avoid it, and why some values en up exactly the mathematical result, is http://stackoverflow.com/questions/18031221/rounding-oddity-what-is-special-about-100/18036308#18036308 – Pascal Cuoq Sep 28 '14 at 07:44
  • To answer for your specific values, `4.35 * 100.0` was likely to end up different from exactly `435.0` because 435 is just below the power of two 512 and 4.35 just above the power of two 4, whereas 4350 is just above the power of two 4096, making `4.35 * 1000.0` unable to produce anything other than `4350.0` – Pascal Cuoq Sep 28 '14 at 07:48
  • PLEASE, PLEASE read [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). It is the canonical answer to this question, which gets asked at least once per day on SO. – Jim Garrison Sep 28 '14 at 09:22
  • 1
    @JimGarrison That document only directly answers this question if one is satisfied with the answer “OMG this is very complicated I'd better treat floating-point error as random”, which is fine as long as one remembers one is making an abstraction. If one is less easily satisfied, then the document you link to only answers the question in the same sense that the Java language definition answers most Java questions on StackOverflow. – Pascal Cuoq Sep 28 '14 at 10:14
  • 1
    You can see what the exact values are using BigDecimal, this will explain way some values round as expected and some should a small error. – Peter Lawrey Sep 28 '14 at 14:30
  • As @PeterLawrey mentioned, BigDecimal can be very useful in understanding the reasons behind floating point results. I can be used to display the exact values of inputs, the result if it is a decimal fraction, the difference between that exact result and the rounded result, and differences between the exact result and the pair of floating point numbers that bracket it. – Patricia Shanahan Sep 28 '14 at 18:53

2 Answers2

1

The computations which do not produce any rounding error are those that can be represented exactly in the binary system. That includes all integers and, e.g, 0.5 decimal which is 0.1 binary or 0.25 decimal which is 0.01 binary. Hence the example you posted has no rounding error. 0.35 decimal however cannot be represented with finitely many binary digits.

Simon Fischer
  • 1,154
  • 6
  • 22
0

There is no way to avoid floating point arithmetic errors. The number of bits used in representing a number will always be finite. All you can do is to use data types with higher precision (bits) like java.math.BigDecimal. Read The need for BigDecimal by John Zukowski for more information. Try this::

import java.math.BigDecimal;

double x = 4.35;
BigDecimal bd1 = BigDecimal.valueOf(x);
BigDecimal bd2= BigDecimal.valueOf(100);
BigDecimal multiply = bd1.multiply(bd2);
System.out.println(multiply);
user2803495
  • 25
  • 1
  • 8