-4

I am well aware that 0.1+0.2 != 0.3 because of precision errors. However I need it to be equal to 0.3.

My solution would be to :

  • Declare an add function that returns the correct double.
  • Inside this function, add the two numbers then round to the 13th digit.

This would work for 0.49999999999999994 and 0.30000000000000004.

How would I implement such a rounding function? Is there another way?

Zezombye
  • 321
  • 4
  • 16
  • Possible duplicate of [Most effective way for float and double comparison](http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison) – SegFault Jul 19 '16 at 17:46
  • 1
    What is "the correct `double`"? You know that `0.3` doesn't really exist, right? – melpomene Jul 19 '16 at 17:46
  • The correct `double` would be in this case the value of `0.3`, so that `add(0.1, 0.2) == 0.3` is true. – Zezombye Jul 19 '16 at 17:48
  • Why do you think `double` is capable of representing `0.3` precisely? – Eugene Sh. Jul 19 '16 at 17:49
  • I know it isn't able to, but I just want the condition to evaluate to true. `add(0.1, 0.2)` would return 0.3. Is it not possible at all? – Zezombye Jul 19 '16 at 17:57
  • 2
    There is no way of representing `0.3` with `double`s, so no, it's not possible. What you can do is find another way of representing it. Fixed-point, string representation, etc... – Banex Jul 19 '16 at 17:58
  • I didn't express myself well enough, I meant that it would return the closest double to 0.3. That way it would be true when comparing to 0.3 (which is really comparing to the closest double to 0.3). – Zezombye Jul 19 '16 at 18:19
  • Multiple both by some arbitrary power of 10, cast to int, then add. When you need to interpret the result, you'll need to take into account the amount you multiplied the 2 numbers by. – Carcigenicate Jul 19 '16 at 18:42
  • Doesn't work; `double a = (int)(16.08*1000) + (int)(0.01*1000); a /= 1000; if (a!=16.09) printf("false");` prints false. This is because 16.08*1000 is less than 16080 (as seen [here](http://stackoverflow.com/questions/588004/is-floating-point-math-broken?rq=1#comment9351332_2607316)). – Zezombye Jul 19 '16 at 18:52

1 Answers1

2

The problem existed from the moment the decimal fractions 0.1 and 0.2 were converted to double, getting 0.1000000000000000055511151231257827021181583404541015625 and 0.200000000000000011102230246251565404236316680908203125. Both are little bigger than the decimal fraction. The nearest double to their sum, 0.3000000000000000444089209850062616169452667236328125, is the next double up from 0.3. The nearest double to 0.3 is smaller, 0.299999999999999988897769753748434595763683319091796875

If you need decimal arithmetic to be exact, not just very, very close, you need to use a decimal arithmetic type, not double.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
  • But couldn't rounding work? For example, 0.3000000000000000444 would be rounded to 0.3000000000000000000, which is then converted to 0.29999999999999998889. Does it not work like that? – Zezombye Jul 20 '16 at 08:54
  • You can't round to 0.3000000000000000000 in double, because it does not exist. – Patricia Shanahan Jul 20 '16 at 09:03
  • 1
    Oh ok, I finally understand what the other comments tried to tell me. I'm going to store my numbers in BCD then. – Zezombye Jul 20 '16 at 09:15