Loki Astari Loki Astari - 10 months ago 55
C++ Question

IEEE 754/iec 559

Is the IEEE 754 floating point format well defined across platforms? In terms of both bit format and endianness?

I am willing to add the following to my code (for an initial version):

static_assert(std::numeric_limits<float>::is_iec559, "Only support IEC 559 (IEEE 754) float");
static_assert(sizeof(float) * CHAR_BIT == 32, "Only support float => Single Precision IEC 559 (IEEE 754)");

static_assert(std::numeric_limits<double>::is_iec559, "Only support IEC 559 (IEEE 754) double");
static_assert(sizeof(float) * CHAR_BIT == 64, "Only support double => Double Precision IEC 559 (IEEE 754)");

static_assert(std::numeric_limits<long double>::is_iec559, "Only support IEC 559 (IEEE 754) long double");
static_assert(sizeof(float) * CHAR_BIT == 128, "Only support long double => Exteneded Precision IEC 559 (IEEE 754)");
// More asserts if required.
// I noticed my current system has a sizeof(long double) => 128
// But numeric_limits<long double>::digits => 63
// So we are not storing quad precision floats only extended.

If I write my float/double/long double in binary format can these be transported between systems without further interpretation. ie...

void write(std::ostream& stream, double value)
stream.write(reinterpret_cast<char const*>(&value), 8);


double read(std::istream& stream)
double value;
stream.read(reinterpret_cast<char*>(&value), 8);
return value;

Or do I need to break the double up into integer components for transport (as suggested by this answer):

The difference here is I am willing to limit my supported representation to IEEE-754 will this basically solve my binary storage of floating point values or do I need to take further steps?

Note: For non conforming platforms (when I find them) I am willing to special case the code so that they read/write IEEE-754 into local representation. But I want to know if the bit/endian is well enough defined cross platform to support storage/transport.


Bit format is well-defined, but not all machines are little-endian. The IEEE standard does not require floating-point numbers to be a certain endian, either. You can run the following program to see the byte pattern of the double 42.0:

#include <stdio.h>
#include <numeric>
#include <limits>
using namespace std;

int main() {
  double d = 42;
  printf("%i\n", std::numeric_limits<double>::is_iec559);
  for (char *c = (char *)&d; c != (char *)(&d+1); c++) {
    printf("%02hhx ", *c);

On an old, unmaintained Sun machine using g++ 3.4.5, this prints

40 45 00 00 00 00 00 00

On an x86_64 machine running a much more recent g++:

00 00 00 00 00 00 45 40