c++ - 编译器使用的 double 表示的显式规范

标签 c++ gcc visual-c++ clang

最近遇到visual-c++好像不是IEEE 754的问题兼容,而是使用 subnormal representation .也就是说,其中的 double float 没有通常表示的 1 个符号位、11 个指数位和 52 个显式存储的有效小数位,见下文。

由于 gccclang 是兼容的,因此非常需要一致的跨平台行为我想知道是否可以强制 visual-c++ 使用正常表示。或者让 gccclang 使用次正规表示当然也可以解决问题。

不同双重表示的问题可以在 visual-c++ 中重现, gccclang使用以下代码:

#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/

相关文章:

c++ - 返回对属性的引用 (GCC)

C++:如何使用堆栈搜索引文

c++ - 错误: cast from ‘void*’ to ‘int’ loses precision [-fpermissive] in makefile

c++ - C++ 中的 sysconf() 错误

c++ - 将 int 矩阵数组放入 C++ 对象时出现问题

mysql - 使用 OCI、MySQL 和 LabView 构建 DLL 一直失败

c++ - 反转 FFT 时没有得到准确的数据

c++ - 在 Turbo C++ 中,可以将普通递归函数转换为尾递归来优化它吗?

C++11 GCC 4.6.2 std::move

c++ - 难以计算圆上一点的角度