浮点格式和isinf()

mad*_*ax1 4 c++ floating-point ieee-754 c++11

我目前正在处理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;
}
Run Code Online (Sandbox Code Playgroud)

根据维基百科,这创建了一个80位扩展精度浮点值,因为我在x86机器上使用GCC.因此0xcccc cccc cccc cccc cccc,浮点值应该是有效值.

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

num = -4.77987e+986
isinf(num) = 1
std::isinf(num) = 0
Run Code Online (Sandbox Code Playgroud)

这让我想知道:

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

Pas*_*uoq 6

isinf,cmath旨在与C语言兼容的函数,需要一个double.传递给该函数时,您的long double参数将被静默转换为double.转化为double产生+inf根据浮点舍入规则(比界限本身稍大大于任何数量的DBL_MAX被舍入到+inf).

相比之下,std::isinf超载,可以采取long double.当你传递它时long double,参数不会被转换,并且std::isinf可以告诉它不是无限的.


要尝试回答您的其他问题:

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

  • DBL_MAXLDBL_MAXfloat.h/ cfloat足够指示IEEE 754双精度(64位格式)或扩展的80位格式之间进行区分.您还可以看看其他宏,如DBL_MANT_DIGLDBL_MANT_DIG,如果你想成为肯定的是,你的代码识别,比方说,四精度20年时普遍处理器实现它(这是不是在2017年的情况).建议不要查看,sizeof(long double)因为80位浮点格式的值可以是10,12或16,具体取决于编译器填充多少,值16也可以表示四精度.