-2

I am struggling with a basic floating-point precision issue. Here is the problem:

double d = 0.1;
d += 0.1;
d += 0.1;

d == 0.3 ? std::cout << "yes" : std::cout << "no";

Run the code and you get "no"

I understand that C/C++ store values in binary and that binary storage can not exactly store every value. I also understand that these small errors compound as you do various math operations on them (i.e. d += 0.1;).

My questions is if I do need to test if d == 0.3 (to a reasonable precision.. as is the clear intent of code above)... how do I do that? I hope the answer is not:

if (d > 0.2999 && d < 0.3001) ...

ALSO.. this works

float f = 0.1;
f += 0.1;
f += 0.1;

f == 0.3f ? std::cout << "yes" : std::cout << "no";

but I can find no equivalent "0.3d" in the language.

Thanks

user1763684
  • 203
  • 3
  • 10
  • 4
    Here we go again... Read this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Paul R May 16 '13 at 13:37
  • because it is not precise. search floating point representation – sashkello May 16 '13 at 13:38
  • Check the [comp.lang.c FAQ](http://c-faq.com/) or the [SO C FAQ](http://stackoverflow.com/questions/tagged/c?sort=frequent&pagesize=50). – Lundin May 16 '13 at 13:55

3 Answers3

3

One common way of testing equality to a certain "tolerance level" is using fabs:

if (fabs(d - 0.3) < 1E-8) {
     ...
}
Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
  • From skimming cppreference.com it appears there are `float` and `double` overloads of `std::abs`, and I can't imagine a reason why there shouldn't be. Only **C** `abs` is integer-specific. So why use `fabs`? –  May 16 '13 at 13:42
  • 1
    @delnan Because the question is tagged as C and C++ :) – Sergey Kalinichenko May 16 '13 at 13:43
  • Didn't notice, thanks. But as OP is using C++ code in the question, I'm assuming that the C tag has little significance. –  May 16 '13 at 13:43
2

You probably need to compare the difference between d and 0.3f with a very small number.

You may try:

 float epsilon = 1e-5;
 if (fabs(d - 0.3f) < epsilon)
 {
     std::cout << "yes" ;
 }
 else{
     std::cout << "no " ;
 }
taocp
  • 22,020
  • 6
  • 46
  • 60
0

0.3f is a float literal. If you want a double literal, you have to use 0.3 (without suffix), as double is the default. 0.3l would be a long double.

DevSolar
  • 59,831
  • 18
  • 119
  • 197
  • Are we seeing the same question? (Perhaps it was edited.) The `0.3f` is used in the second snippet, where f is a `float`. There is no `0.3l` in the question. –  May 16 '13 at 13:46
  • @delnan: I answered this part of the question (seeing how `std::abs()` / `fabs()` was already covered by others): *"...but I can find no equivalent "0.3d" in the language."* – DevSolar May 16 '13 at 13:48
  • I misread the part about `0.3l` (the explanation that `0.3` is a double made sense), and as a consequence misread the intent of your answer. Never mind. –  May 16 '13 at 13:50