Boost C++ Libraries of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards


Exact-Width Floating-Point typedefs

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 typedefs 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

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

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

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

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

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:


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


and the maximum number of possibly significant decimal digits using

[Tip] 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] 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.