IEEE 754浮点格式是否跨平台定义良好?在位格式和字节序方面?
我愿意将以下内容添加到我的代码中(初始版本):
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.
如果我以二进制格式编写float / double / long double,可以在系统之间传输这些,而无需进一步解释。即...
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;
}
或者我是否需要将双重分解为整数组件以进行传输(如this answer所示):
这里的区别是我愿意将我支持的表示限制为IEEE-754这是否基本上解决了浮点值的二进制存储问题,还是需要采取进一步措施?
注意:对于不符合要求的平台(当我找到它们时)我愿意特殊情况下的代码,以便他们将IEEE-754读/写成本地表示。但我想知道bit / endian是否足够好定义跨平台以支持存储/传输。
答案 0 :(得分:3)
位格式定义明确,但并非所有机器都是小端的。 IEEE标准也不要求浮点数是某个字节序。您可以运行以下程序来查看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);
}
printf("\n");
}
在使用g ++ 3.4.5的旧的,未维护的Sun机器上,打印
1
40 45 00 00 00 00 00 00
在运行更新近g ++的x86_64机器上:
1
00 00 00 00 00 00 45 40
答案 1 :(得分:1)
首先,您可能希望更改代码,以便正确检查类型大小......
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(double) * 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(long double) * CHAR_BIT == 128, "Only support long double => Exteneded Precision IEC 559 (IEEE 754)");
问题是,IEEE-754不需要长两倍的128位长。根据编译器和平台的不同,此类型的长度可能会有所不同。但它确实指定了binary128,编译器可能支持也可能不支持它,具体取决于平台和实现(gcc具有非标准的__float128类型)。标准只要求long double至少精确到double,使其通常为80 bit(gcc)或64(VS)。
如果您将支持的表示限制为IEEE-754,则不应遇到任何问题。
答案 2 :(得分:0)
要便携地读写IEEE 754,请使用这些例程。 如果平台不是IEEE 754,您可能会丢失几个位,但是 你仍然可以获得最接近的代表性。