Representable result of floor() and ceil()

c, ceil, floating-point, floor, ieee-754

Solution

This is guaranteed by the construction of IEEE-754 numbers. (To be clear: C does not guarantee IEEE-754, but the following analysis holds for all other floating-point formats with which I am familiar as well; the crucial property is that all sufficiently large numbers in the format are integers).

Recall that a normal IEEE-754 number has the form `±1.xxx...xxx * 2^n`, where the width of the significand field (the `xxx...xxx` part) is defined by the type of the number (23 binary digits for single precision, 52 binary digits for double precision). All such numbers with an exponent (`n`) within the allowed range are representable.

Assume WLOG that `v` is positive (if `v` were negative, we could swap `ceil` and `floor` in the following analysis).

Let `v` have `k` significant bits, and write `v` out as a binary fixed point number; there are three possibilities:

Case 1: All significand bits are integral. When we write out `v`, it looks like this

xxxxxxxxxxxxxxxxxxxxxxxx000000...00000.0

then `v` is an integer, and so `ceil(v) = floor(v) = v`, and so both are trivially representable.

Case 2: All significand bits are fractional. When we write out `v`, it looks like

0.000000...00000xxxxxxxxxxxxxxxxxxxxxxxx

then `v` is in the range [0,1), and so `floor(v) = 0`, which is representable, and `ceil(v)` is either zero or one, both of which are representable.

Case 3: `v` contains both integral and fractional significand bits:

xxxxxxxxxxxxxx.xxxxxxxxxx

then `floor(v)` is just:

xxxxxxxxxxxxxx.

because we have thrown away at least one fractional bit, `floor(v)` has at most `k-1` significant bits, and the same exponent as `v`, so it is representable.

If `v` is an integer, then `ceil(v) = floor(v) = v`, so `ceil(v)` is representable. Otherwise, `ceil(v) = floor(v) + 1`, and so also has at most `k-1` significant bits and is also representable.

Problem

For an arbitrary value 'v' of a floating point type (float/double/long double), does C89 guarantee that the mathematically exact integer result of floor(v) and ceil(v) is a representable value of the type of 'v'? Does any of the later C or C++ standards guarantee this? Does IEEE 754 guarantee this?

Original source