浮点格式和isinf()

时间:2017-10-26 12:19:33

标签: c++ c++11 floating-point ieee-754

我目前正在处理C ++中的浮点值。 请考虑以下c ++代码段:

#include <cmath>
#include <cstring>
#include <iostream>

int main() {
    long double num;

    // Set num to a large, valid, floating point value
    memset(&num, 0xcc, sizeof(num));

    std::cout << "num = " << num << std::endl;
    std::cout << "isinf(num) = " << isinf(num) << std::endl;
    std::cout << "std::isinf(num) = " << std::isinf(num) << std::endl;

    return 0;
}

根据Wikipedia,这会创建一个80位extended precision浮点值,因为我在x86机器上使用GCC。因此,浮点值为0xcccc cccc cccc cccc cccc,并且应该是有效值。

有趣的是,输出结果如下:

num = -4.77987e+986
isinf(num) = 1
std::isinf(num) = 0

这让我想知道:

  • 为什么isinfstd::isinf表现得与众不同?哪一个值得信任?
  • Here它说在C99中,isinf是一个宏,而在C ++ 11中,它变成了一个函数。但是,当我编译例子时,例如与-std=c++98,我仍然得到相同的行为。在这种情况下,甚至不能定义std::isinf吗?
  • 一般来说,我怎么知道我的编译器/架构使用哪种浮点格式?

1 个答案:

答案 0 :(得分:6)

isinfcmath中旨在与C语言兼容的函数需要double。传递给该函数时,您的long double参数会以静默方式转换为double。转换为double会根据浮点舍入规则生成+inf(任何大于限制本身略大于DBL_MAX的数字都会舍入为+inf)。

相比之下,std::isinfoverloaded,可以long double。当你传递long double时,参数不会被转换,而std::isinf可以告诉它不是无限的。

试着回答你的其他问题:

  • isinf是宏还是函数是一个小细节。知道它是一个宏只对想要#undef它的程序员来说很方便。无论是函数还是保证是宏,它的行为都相同(将其参数转换为double)。

  • 来自DBL_MAX / LDBL_MAX
  • float.hcfloat足以区分IEEE 754双精度(64位格式)或扩展80位格式。您还可以查看其他宏,例如DBL_MANT_DIGLDBL_MANT_DIG,如果您想确定您的代码在广泛的处理器实现它的20年内识别出四倍精度(这不是2017年的情况)。建议不要查看sizeof(long double),因为80位浮点格式的值可以是10,12或16,具体取决于编译器填充多少,值16也可以表示四精度