【问题标题】:Epsilon in quadruple precision (gcc)四倍精度 (gcc) 的 Epsilon
【发布时间】:2020-03-24 00:52:17
【问题描述】:

根据维基百科,不同精度数据类型的布局是

我写了一个小程序输出C++中float、double和long double的数值限制(用g++编译) p>

#include<iostream>
#include<limits>
#include<string>

template<typename T>
void print(std::string name) {
    std::cout << name << " (" << sizeof(T) * 8 << "): " << std::numeric_limits<T>::epsilon() << "\t"  <<  std::numeric_limits<T>::min() << "\t" <<  std::numeric_limits<T>::max() << std::endl;
}

int main() {
    std::cout.precision(5);
    print<float>("float");
    print<double>("double");
    print<long double>("long double");
    return 0;
}

哪些输出(我在多台机器上运行过,结果相同)

float (32): 1.1921e-07  1.1755e-38  3.4028e+38
double (64): 2.2204e-16 2.2251e-308 1.7977e+308
long double (128): 1.0842e-19   3.3621e-4932    1.1897e+4932

上限与 2^(2^(e-1)) 一致,对于 float 和 double,epsilon 与 2^(-f) 一致。对于 long double,按照这种逻辑,epsilon 应该大约为 1.9259e-34。

有谁知道,为什么不呢?

【问题讨论】:

    标签: c++ epsilon quadruple-precision


    【解决方案1】:

    long double 不保证实现为 IEEE-745 四倍精度。 C++ reference reads:

    long double - 扩展精度浮点类型。不一定映射到 IEEE-754 规定的类型。通常是 x86 和 x86-64 架构上的 80 位 x87 浮点类型。

    如果 long double 实现为 80-bits x86 extended precision,则 epsilon 为 2<sup>-63</sup> = 1.0842e-19。这是您作为输出获得的值。

    某些编译器 support __float128 类型具有四倍精度。在 GCC 中,long double 成为 __float128 的别名,如果使用了 -mlong-double-128 命令行选项,并且在 x86_64 目标上,__float128 是 guaranteed 为 IEEE 四倍精度类型(在软件中实现)。

    std::numeric_limits 不是专用于__float128。要获得 epsilon 的值,可以使用以下技巧(假设是 little-endian 机器):

    __float128 f1 = 1, f2 = 1;      // 1.q       -> ...00000000
    std::uint8_t u = 1;
    std::memcpy(&f2, &u, 1);        // 1.q + eps -> ...00000001
    std::cout << double(f2 - f1);   // Output: 1.9259e-34
    

    使用 GCC,您可以使用 libquadmath:

    #include <quadmath.h>
    ...
    
    std::cout << (double)FLT128_EPSILON;
    

    获得相同的输出。

    【讨论】:

    • 谢谢!我想我对 long double 占用 128 位这一事实感到恼火。
    • 您关于 x86_64 GCC 保证的句子似乎含糊不清或不正确。特别是,如果您的意思是 long double 默认保证在 x86_64 上是 IEEE binary128,那么这是错误的。 x86_64 上没有对binary128 的硬件支持,因此它不能是 GCC 上的默认内置类型。
    • @Ruslan,我既不是说__float128 有硬件支持,也不是说long double 默认与__float128 相同。 GCC 文档中写道:“支持 __float128 (TFmode) IEEE quad 类型……可通过 x86_64 目标上的 soft-fp 库获得。”。我编辑了答案以澄清它。
    • 我和@Ruslan 一样感到困惑:'it' 指的是什么?到之前发生的最后一个主题。不幸的是,这是 'long double'('[...] 变成了别名 [...]')。希望你不介意我修好了 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-23
    • 2012-11-14
    • 2015-04-06
    • 2018-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多