1

I am trying to calculate the product of the following two doubles:

double x = 196.0d;
double y = 0.5144d;

double z = x * y;

The answer to this should be z = 100.8224; but java calculates it as z = 100.82239999999999;

What is causing this?

Eduardo
  • 6,183
  • 12
  • 61
  • 109
  • 1
    This is the issue with (microscopic!) inaccuracies with doubles, many decimal numbers (like 0.5144) can't be exactly expressed in binary, much like 1/3 can't be expressed exactly in decimal – Richard Tingle Oct 21 '13 at 10:27
  • See this related question; http://stackoverflow.com/questions/16707397/whats-wrong-with-this-simple-double-calculation or http://stackoverflow.com/a/19089461/2187042 – Richard Tingle Oct 21 '13 at 10:27
  • http://en.wikipedia.org/wiki/Double-precision_floating-point_format – Suresh Atta Oct 21 '13 at 10:31

3 Answers3

5

The nearest double-precision floating point number to 0.5144 is 4633303296638766 / 2 ^ 53, which is actually 0.51439999999999996838084825867554. However, Java displays this as 0.5144, because it has heuristics for picking a number with fewer decimal places in the event that there is one that is close enough to a given double-precision floating point number.

When you multiply that same number by 196 though, the error is compounded, and you finish with 100.82239999999999380264625870041. This is not close enough to 100.8224 to be displayed as 100.8224, because there is another double-precision floating point number that is closer to 100.8224.

Dawood ibn Kareem
  • 68,796
  • 13
  • 85
  • 101
2

Try DecimalFormat

        DecimalFormat decimalFormat = new DecimalFormat("##,###,###.####");
        decimalFormat.format(z);
        System.out.println(decimalFormat.format(z));
newuser
  • 7,892
  • 2
  • 23
  • 33
0

You can do it like this:

        double x = 196.0d;
        double y = 0.5144d;
        BigDecimal bigdec = new BigDecimal(x).multiply(new BigDecimal(y));
        bigdec = bigdec.setScale(4, BigDecimal.ROUND_HALF_UP);
        System.out.println(bigdec.doubleValue());
Jhanvi
  • 4,744
  • 8
  • 30
  • 41
  • It would be better to have, on the third line, `BigDecimal bigdec = new BigDecimal(x).multiply(new BigDecimal(y));` - that way, the imprecision never exists in the first place, and doesn't need to be rounded away. – Dawood ibn Kareem Oct 21 '13 at 10:46
  • @DavidWallace you are right, thanks for pointing it out. – Jhanvi Oct 21 '13 at 10:48
  • 1
    Now that you've changed the third line, you can remove the fourth line. It now does nothing, because `bigdec` already has the right scale. You also don't need the call to `doubleValue` on the fifth line. – Dawood ibn Kareem Oct 21 '13 at 10:48
  • @DavidWallace actually , some confusion here, by fourth line, the value does round up, upto 4 digits, without it, the answer is :100.82239999999999. – Jhanvi Oct 21 '13 at 10:52
  • No. You're now doing decimal multiplication, rather than floating point multiplication, because of your change to the third line. So `bigdec` is exactly 100.8224. – Dawood ibn Kareem Oct 21 '13 at 10:53
  • I compiled it after removing fourth line, its not giving me 100.8224, can you please let me know what i am doing wrong?? – Jhanvi Oct 21 '13 at 10:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/39641/discussion-between-david-wallace-and-jhanvi) – Dawood ibn Kareem Oct 21 '13 at 11:01
  • Ooh, yes, I was wrong here. Jhanvi, thanks for correcting me. The problem is that as soon as you write new `BigDecimal(y)`, you have a `BigDecimal` that equals the imprecise `double` value, not the exact 0.5144. The moral of this exercise is always to create your `BigDecimal` values from `String` values, not from `double` values, because as soon as you have a `double`, you've probably already got an imprecision. If you use `new BigDecimal("0.5144")`, this works correctly. – Dawood ibn Kareem Oct 21 '13 at 11:12
  • The [documentation for the BigDecimal(double) constructor](http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#BigDecimal%28double%29) makes a point of warning programmers of this. – VGR Oct 21 '13 at 23:45