Because 0.1 not 0.1; this value does not appear to be double precision, so it is rounded to the nearest double precision number, which is exactly:
0.1000000000000000055511151231257827021181583404541015625
When you call fmod , you get the remainder of the division by the above value, which is equal to:
0.0999999999999999500399638918679556809365749359130859375
which is rounded to 0.1 (or possibly 0.09999999999999995 ) when printed. A.
In other words, fmod works fine, but you do not give it the input that you consider yourself to be.
Edit: Your own implementation gives the correct answer, because it is less accurate, believe it or not. First of all, note that fmod calculates the remainder without any rounding error; the only source of inaccuracy is a presentation error introduced using a value of 0.1 . Now let's look at your implementation and see how the rounding error that it carries exactly cancels the presentation error.
Rate a - floor(a/n) * n one step at a time, keeping track of the exact values ββcalculated at each step:
First we estimate 1.0/n , where n is the closest double precision approximation to 0.1 , as shown above. The result of this division is approximately equal to:
9.999999999999999444888487687421760603063276150363492645647081359...
Please note that this value is not a double precision representable number, therefore it is rounded. To see how this rounding occurs, let's look at a number in binary instead of decimal:
1001.1111111111111111111111111111111111111111111111111 10110000000...
The space indicates where rounding to double precision occurs. Since the part after the round point is larger than the exact half point, this value is rounded to an accuracy of 10 .
floor(10.0) is expected to be 10.0 . So all that remains is to calculate 1.0 - 10.0*0.1 .
In binary terms, the exact value is 10.0 * 0.1 :
1.0000000000000000000000000000000000000000000000000000 0100
again, this value does not appear to be double, and therefore is rounded at the position indicated by a space. This time it is rounded to the precision of 1.0 , so the final calculation is 1.0 - 1.0 , which of course is 0.0 .
There are two rounding errors in your implementation that exactly eliminate the error in representing the value 0.1 . fmod , by contrast, is always accurate (at least on platforms with a good number library) and produces a 0.1 representation error.