Is a float guaranteed to be preserved when transported through a double in C/C++?

You don’t even need to assume IEEE. C89 says in 3.1.2.5:

The set of values of the type float is a subset of the set of values
of the type double

And every other C and C++ standard says equivalent things. As far as I know, NaNs and infinities are “values of the type float“, albeit values with some special-case rules when used as operands.

The fact that the float -> double -> float conversion restores the original value of the float follows (in general) from the fact that numeric conversions all preserve the value if it’s representable in the destination type.

Bit-level representations are a slightly different matter. Imagine that there’s a value of float that has two distinct bitwise representations. Then nothing in the C standard prevents the float -> double -> float conversion from switching one to the other. In IEEE that won’t happen for “actual values” unless there are padding bits, but I don’t know whether IEEE rules out a single NaN having distinct bitwise representations. NaNs don’t compare equal to themselves anyway, so there’s also no standard way to tell whether two NaNs are “the same NaN” or “different NaNs” other than maybe converting them to strings. The issue may be moot.

One thing to watch out for is non-conforming modes of compilers, in which they keep super-precise values “under the covers”, for example intermediate results left in floating-point registers and reused without rounding. I don’t think that would cause your example code to fail, but as soon as you’re doing floating-point == it’s the kind of thing you start worrying about.

Leave a Comment