最近遇到visual-c++
好像不是IEEE 754的问题兼容,而是使用 subnormal representation .也就是说,其中的 double float 没有通常表示的 1 个符号位、11 个指数位和 52 个显式存储的有效小数位,见下文。
由于 gcc
和 clang
是兼容的,因此非常需要一致的跨平台行为我想知道是否可以强制 visual-c++
使用正常表示。或者让 gcc
和 clang
使用次正规表示当然也可以解决问题。
不同双重表示的问题可以在 visual-c++
中重现, gcc
和 clang
使用以下代码:
#include <iostream>
#include <string>
int main()
{
try {
std::stod("8.0975711886543594e-324");
std::cout << "Subnormal representation.";
} catch (std::exception& e) {
std::cout << "Normal representation.";
}
return 0;
}
是否有可能在所有三种情况下产生一致行为的表示规范?
编辑:作为geza指出,这在 std::stod
的不同实现中出现问题,这将提出一个问题,是否有任何方法可以使 std::stod
行为一致而不必为其实现单独的包装器。
最佳答案
不幸的是,std::stod
设计得很糟糕,因为无法确定是什么导致了 std::out_of_range
异常。
我建议您改用strtod
。虽然标准中没有指定此函数对次正规数应该做什么,但它通常对次正规数表现良好(这意味着它返回次正规数)。该函数的好处是对于超出范围的情况,它返回一个有意义的结果,因此可以确定超出范围的原因。
如果你想处理超出范围的情况,你需要检查 errno
是否有 ERANGE
。请注意,如果结果是次正规数/零数,则可能 errno
将设置为 ERANGE
,您应该忽略它(您可以使用 检查这一点fpclassify
).
所以逻辑是这样的:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
关于c++ - 编译器使用的 double 表示的显式规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53375554/