15

As everybody knows, you have limited precision when you use printf to output the value of a float.
However, there is a trick to increase the accuracy in the output, as this example shows:

#include <stdio.h>

int main()
{
    float f = 1318926965;        /* 10 random digits */
    printf("%10.f\n", f);        /* prints only 8 correct digits */
    printf("%10d\n", *(int*)&f); /* prints all digits correctly */
    return 0;
}

and my question is, why don't people use this trick more often?

6
  • 1
    Because potentially undefined behavior is bad. (Edit: Technically it may not be undefined behavior, as I'm not sure what the standard says about it. Endianess could bite you with this though.) Commented Apr 1, 2012 at 8:53
  • 9
    +1 for a good April's 1st joke! Commented Apr 1, 2012 at 9:03
  • It apparently got me x.x Commented Apr 1, 2012 at 9:16
  • 1
    You should have used an union for an irreproachable April's fool joke. Commented Apr 1, 2012 at 9:33
  • 1
    @MrLister I'm not saying that your program is too readable, I am saying that it is too undefined. Look up "strict aliasing rules" tomorrow. Commented Apr 1, 2012 at 12:17

3 Answers 3

11

April fool?

Your "random number" 1318926965 have the same underlying representation both in decimal and floating-point form.

Try another value, like 10. It will print as:

        10
1092616192

So to answer your question:

and my question is, why don't people use this trick more often?

Because only one day of the year is April Fools Day... The rest of the days the trick doesn't work...

Sign up to request clarification or add additional context in comments.

1 Comment

1318926965 does not have the same representation in the binary32 floating-point format because it is not representable in binary32. Conversion to binary32 rounds to the nearest representable value, which is 1318926976, whose representation in binary32 has the same bits as 1318926965 in binary.
4

Try that same trick with a different number, say 2318926965.

#include <stdio.h>

int main()
{
    float f = 2318926965;        /* 10 random digits */
    printf("%10.f\n", f);        /* prints only 8 correct digits */
    printf("%10d\n", *(int*)&f); /* prints all digits correctly */
    return 0;
}
$ gcc -Wall -O3  t.c
t.c: In function ‘main’:
t.c:7:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
$ ./a.out 
2318926848
1326069764

I don't see an increase in precision at all with your "trick" that depends on the bit representation of floats on your platform (as far as I understand it).

This thread has a few other of these "magic floats" and a way to generate them.

3 Comments

It depends on the bit representation of floats per IEEE 754, not "on your platform". (Modulo possible byte order issues that don't exist on any real-world machines.) IMO the only thing bad about code like this is the improper type-punning which should be replaced with unions (sketchy but intentionally supported by all compilers) or memcpy (100% legal C).
If IEEE 754 is mandatory, what's the use for the __STDC_IEC_559__ define?
It's not mandatory, but considering how broken the C standard allows non-IEEE-conformant implementations' floating point to be, and that there's no other way you can tell what you can rely on in regards to floating point arithmetic, I would consider it a huge mistake for programs that want to be portable to non-IEEE-math systems to use floating point whatsoever. (Naturally however you could use it on a non-portable program intended only for use on a single non-IEEE-math implementation.)
-1

The limit to precision is with the floating point representation, not with printf() it is a false premise.

Moreover a single precision float is only guaranteed correct to 6 digits of precision, so the "trick" would be fooling yourself; in the general case it would not work.

If you want 10 digit floating-point numbers then you should use double precision, which is good for 15 digits.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.