-3

Given the following doubles, does fmod return the correct value?

    double x = .090;
    double y = .003;
    double r = fmod(x, y);
    // r = 0.0029999999999999949

Why doesn't r = 0?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
jbassking
  • 525
  • 1
  • 5
  • 20
  • 3
    ... because, in general, floating point numbers can't exactly represent base-10 fractions. This question has been answered here hundreds of times already. – Carl Norum Jul 26 '13 at 14:25
  • 2
    consider removing tag visual-c++ this has nothing to do with visual-c++ – UpAndAdam Jul 26 '13 at 14:27

2 Answers2

6

Because, like most decimal fractions, these numbers can't be represented exactly by a binary floating point format. To see what values are actually being used:

#include <cstdio>

int main() {
    printf("%.20f %.20f\n", .090, .003);
}

Output: 0.08999999999999999667 0.00300000000000000006

These small rounding errors mean that the first value is slightly less than an exact multiple of the second, hence the result you see.

You may want to allow a small tolerance for error:

if (r > y - some_small_value) {
    r = 0;
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
3

This type of question can be resolved by reading a paper entitled What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Your machine uses a binary representation for floating-point numbers which cannot exactly represent the rational number 3/1000 = 0.003.

Of course, the machine can print its approximation of 0.003 as "0.003", but that's being done by the formatted printing code inside printf, when it rounds off the value to a given number of decimal digits.

The difference between the printed, decimal versions of floating-point values and their actual internal values can create problems for the programmer or user who isn't aware of the issues.

Kaz
  • 55,781
  • 9
  • 100
  • 149