There and back again: riddle for floating-point numbers (almost no tricks)


Few days ago I saw that and thought, that it could be interesting. Nothing complex, special, mostly well-known knowledge, just an unusual angle.


The riddle: You have a simple program in C/C++ that write a floating-point (double) number into a file, and then reads it from there using simple printf and scanf. There is nothing else in this file. As an example, the function below does the same with a simple string buffer instead of a file:



void qu(double g)
{
 char buf[2000];
 sprintf(buf,"%lf\n", g);
 fputs(buf,stdout);
 double q = 0;
 int n = sscanf(buf,"%lf",&q);
 printf("Got back %d numbers = %lf\n\n", n, q);
}


The question: will it always work? Will you always get what you put inside (putting aside evident rounding for text representation)?


-------------------- the answer (gray on gray, select to see the text) ----------------


Nope. IEEE standard for floating-point numbers defines a couple of unusual numbers like ±infinity of ±Not-a-Number (nan). Here is an example of calling the function above that will read different values than those, you tried to print:



#include <windows.h>
#include <stdio.h>


int wmain(int argc, WCHAR* argv[])
{
 float f0 = 0;
 unsigned long nan[2]={0xffffffff, 0x7fffffff};
 double g = *( double* )nan;
 qu(g);


 nan[1] = 0xffffffff;
 g = *( double* )nan;
 qu(g);


 g = 5.0/f0;
 qu(g);


 g = -5.0/f0;
 qu(g);


 return 0;
}


And the output from this code will look like:



1.#QNAN0 1.#QNAN0e+000
Got back 1 numbers = 1.000000


-1.#QNAN0 -1.#QNAN0e+000
Got back 1 numbers = -1.000000


1.#INF00 1.#INF00e+000
Got back 1 numbers = 1.000000


-1.#INF00 -1.#INF00e+000
Got back 1 numbers = -1.000000


The problem is that scanf() does not recognize some of the output formats created by printf(). “1.#QNAM0” it considers to be “1.” and some text data afterward.


------------------------ end of the answer -------------------

Skip to main content