Search code examples
c++language-lawyerc++14floating-point-conversion

Is round-trip through floating point always defined behavior if floating point range is bigger?


Let's say I have two arithmetic types, an integer one, I, and a floating point one, F. I also assume that std::numeric_limits<I>::max() is smaller than std::numeric_limits<F>::max().

Now, let's say I have a positive integer value i. Because the representable range of F is larger than I, F(i) should always be defined behavior.

However, if I have a floating point value f such that f == F(i), is I(f) well defined? In other words, is I(F(i)) always defined behavior?


Relevant section from the C++14 standard:

4.9 Floating-integral conversions [conv.fpint]

  1. A prvalue of a floating point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type. [ Note: If the destination type is bool, see 4.12. — end note ]
  2. A prvalue of an integer type or of an unscoped enumeration type can be converted to a prvalue of a floating point type. The result is exact if possible. If the value being converted is in the range of values that can be represented but the value cannot be represented exactly, it is an implementation-defined choice of either the next lower or higher representable value. [ Note: Loss of precision occurs if the integral value cannot be represented exactly as a value of the floating type. — end note ] If the value being converted is outside the range of values that can be represented, the behavior is undefined. If the source type is bool, the value false is converted to zero and the value true is converted to one.

Solution

  • No.

    It's possible that i == std::numeric_limits<I>::max(), but that i is not exactly representable in F.

    If the value being converted is in the range of values that can be represented but the value cannot be represented exactly, it is an implementation-defined choice of either the next lower or higher representable value.

    Since the next higher representable value may be chosen, it's possible that the result F(i) no longer fits into I, so conversion back would be undefined behavior.