-4

I came across this code recently. It produces strange results (lots of random digits after about the 18th digit.) I tried to find information on the limits to sprintf but could not find it. I am trying to figure out if the answer is actually correct or just garbage. When passed 0.025 (as a double) it prints out:

0.025000000000000001387778780781445675529539585113525390625

#define MAX_NUM_STR_LEN 128
void File_WriteNumber(File *fp, double value) {
    char numbuf[MAX_NUM_STR_LEN];
    int sz = sprintf(numbuf, "%.100g", value);
    fwrite (numbuf , sizeof(char), sz, fp);
}
Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • 2
    https://stackoverflow.com/questions/588004/is-floating-point-math-broken – yano Jul 28 '17 at 19:55
  • Are you passing `0.25` or `0.025`? – Michael Albers Jul 28 '17 at 19:56
  • @MichaelAlbers oops. Corrected. – Jiminion Jul 28 '17 at 20:00
  • 10e50 same questions on internet. Do some researches yourself before asking. Respect our time. Google should become your best friend – 0___________ Jul 28 '17 at 20:06
  • its actually limits on the precision of double https://en.wikipedia.org/wiki/Double-precision_floating-point_format – pm100 Jul 28 '17 at 20:09
  • 1
    The answer is that (s)printf is behaving properly here. You need to learn about floating point, and the fact that decimal numbers like 0.1 and 0.025 cannot be represented exactly. Try a number like 0.25 or 0.125, and you shouldn't see any garbage (since those numbers *do* have exact representations in base-2 floating point). – Steve Summit Jul 28 '17 at 20:14
  • You were printing `1/40` which is exactly representable in the decimal system but not in a binary system. Consider `1/3` or `1/7` which are not exactly representable in either system. You surely understand the situation in the decimal system, and similar applies to binary. The representations are not finite, or even within the precision available. – Weather Vane Jul 28 '17 at 20:18
  • The Wikipedia page on [Double-precision floating-point format](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) says of the format: *This gives from 15 to 17 significant decimal digits precision.* – Weather Vane Jul 28 '17 at 20:26

1 Answers1

4

Answer is actually correct - not random digits.


double can typically represent exactly about 264 different values.

0.025 is not one of them with a binary64 double.

The closest double is 0.025000000000000001387....
The next closest double is 0.024999999999999997918...

sprintf() is doing just fine.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256