Exact-Width Floating-Point typedefs

| Home | Libraries | People | FAQ | More

## Exact-Width Floating-Point `typedef`s

The `typedef float#_t`, with # replaced by the width, designates a floating-point type of exactly # bits. For example `float32_t` denotes a single-precision floating-point type with approximately 7 decimal digits of precision (equivalent to binary32 in IEEE_floating_point).

Floating-point types in C and C++ are specified to be allowed to have (optionally) implementation-specific widths and formats. However, if a platform supports underlying floating-point types (conformant with IEEE_floating_point) with widths of 16, 32, 64, 80, 128 bits, or any combination thereof, then `<boost/cstdfloat.hpp>` does provide the corresponding `typedef`s `float16_t, float32_t, float64_t, float80_t, float128_t,` their corresponding least and fast types, and the corresponding maximum-width type.

##### How to tell which widths are supported

The definition (or not) of a floating-point constant macro is a way to test if a specific width floating-point is available on a platform.

    #if defined(BOOST_FLOAT16_C)
    // Can use boost::float16_t, perhaps a proposed __short_float.
    // P0192R1, Adding Fundamental Type for Short Float,
    // Boris Fomitchev, Sergei Nikolaev, Olivier Giroux, Lawrence Crowl, 2016 Feb14
    // http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2016.pdf
    #endif

    #if defined(BOOST_FLOAT32_C)
    // Can use boost::float32_t, usually type `float`.
    #endif

    #if defined(BOOST_FLOAT64_C)
    // Can use boost::float64_t, usually type `double`, and sometimes also type `long double`.
    #endif

    #if defined(BOOST_FLOAT80_C)
    // Can use boost::float80_t, sometimes type `long double`.
    #endif

    #if defined(BOOST_FLOAT128_C)
    // Can use boost::float128_t. Sometimes type `__float128` or `_Quad`.
    #endif

This can be used to write code which will compile and run (albeit differently) on several platforms. Without these tests, if a width, say `float128_t` is not supported, then compilation would fail. (It is, of course, rare for `float64_t` or `float32_t` not to be supported).

The number of bits in just the significand can be determined using:

    std::numeric_limits<boost::floatmax_t>::digits

and from this one can safely infer the total number of bits because the type must be IEEE754 format, `std::numeric_limits<boost::floatmax_t>::is_iec559 == true`, so, for example, if `std::numeric_limits<boost::floatmax_t>::digits == 113`, then `floatmax_t` must be`float128_t`.

The total number of bits using `floatmax_t` can be found thus:

    const int fpbits =
      (std::numeric_limits<boost::floatmax_t>::digits == 113) ? 128 :
      (std::numeric_limits<boost::floatmax_t>::digits == 64) ? 80 :
      (std::numeric_limits<boost::floatmax_t>::digits == 53) ? 64 :
      (std::numeric_limits<boost::floatmax_t>::digits == 24) ? 32 :
      (std::numeric_limits<boost::floatmax_t>::digits == 11) ? 16 :
      0; // Unknown - not IEEE754 format.
     std::cout << fpbits << " bits." << std::endl;

and the number of 'guaranteed' decimal digits using

    std::numeric_limits<boost::floatmax_t>::digits10

and the maximum number of possibly significant decimal digits using

    std::numeric_limits<boost::floatmax_t>::max_digits10

| Tip
`max_digits10` is not always supported, but can be calculated at compile-time using the Kahan formula, `2 + binary_digits * 0.3010` which can be calculated at compile time using `2 + binary_digits * 3010/10000`.

| Note
One could test that std::is_same<boost::floatmax_t, boost::float128_t>::value == true but this would fail to compile on a platform where `boost::float128_t` is not defined. So it is better to use the MACROs `BOOST_FLOATnnn_C`.