Conversion from double to float, and undefined behaviour.

M

Mark Dickinson

I'm dealing with some code that (for the purposes of serialization)
explicitly
casts a double to a float. In essence, it looks like this:

#include <math.h>
#include <stdio.h>

void f(double x) {
float y = x;

if (isinf(y) && !isinf(x))
printf("Deal with overflow here\n");
else
printf("Do something with %.17g\n", y);
}

However, according to C99 6.3.1.5p2, converting a finite value that's
"outside
the range of values that can be represented" as a float gives
undefined behaviour.
How would you rewrite the above to avoid undefined behaviour? The
obvious
solution is to check whether fabs(x) > FLT_MAX before converting.

But:

This isn't quite the same thing, since some values that are *only
just* greater
than FLT_MAX would normally be expected to round down to FLT_MAX, so
the
boundary is actually something like (assuming IEEE 754 floats and
doubles)

FLT_MAX / (1 - 0.5 * FLT_EPSILON) * (1 - 0.25 * FLT_EPSILON)

So the question is: what's the exact meaning of "outside the range of
values
that can be represented" in C99 6.3.1.5p2? For converting from double
to
float, is the relevant range only up to (and including) FLT_MAX, or
can I
assume that I'm safe all the way up to (but not including) the
slightly larger
bound above?

(Note: on the platforms I care about, it's realistic to assume that
double
and float are IEEE 754 binary64 and binary32 formats, respectively,
and
that conversion from double to float uses round-half-to-even.)
 
B

Ben Bacarisse

Mark Dickinson said:
I'm dealing with some code that (for the purposes of serialization)
explicitly
casts a double to a float. In essence, it looks like this:

#include <math.h>
#include <stdio.h>

void f(double x) {
float y = x;

if (isinf(y) && !isinf(x))
printf("Deal with overflow here\n");
else
printf("Do something with %.17g\n", y);
}

However, according to C99 6.3.1.5p2, converting a finite value that's
"outside the range of values that can be represented" as a float gives
undefined behaviour. How would you rewrite the above to avoid
undefined behaviour? The obvious solution is to check whether fabs(x)

But:

This isn't quite the same thing, since some values that are *only
just* greater than FLT_MAX would normally be expected to round down to
FLT_MAX, so the boundary is actually something like (assuming IEEE 754
floats and doubles)

FLT_MAX / (1 - 0.5 * FLT_EPSILON) * (1 - 0.25 * FLT_EPSILON)

So the question is: what's the exact meaning of "outside the range of
values that can be represented" in C99 6.3.1.5p2?

I can't really address the underlying issue, but the wording seems to be
unambiguous. The C standard defines a model of floating point numbers
in which there is an unambiguous range of representable numbers.
Likewise the value being converted is an exact rational number and will
either be in or outside of the range of the target type.

It is possible that the standard intended to include rounding in this
phrase, but that seems unlikely since it is explicitly mentioned in the
preceding sentences.
For converting from double to float, is the relevant range only up to
(and including) FLT_MAX, or can I assume that I'm safe all the way up
to (but not including) the slightly larger bound above?

(Note: on the platforms I care about, it's realistic to assume that
double and float are IEEE 754 binary64 and binary32 formats,
respectively, and that conversion from double to float uses
round-half-to-even.)

The fact that you mention a specific FP implementation suggests that you
are not so much concerned with what the standard says is UB but what
IEEE FP systems actually do in these situations. That I can't speak to.

The fact the C makes it UB does not mean that anything bad will happen.
It simply gives implementations license do what they like -- probably
because some FP systems "go wrong" in exactly this situation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top