【问题标题】:Floating point formats and isinf()浮点格式和 isinf()
【发布时间】:2017-10-28 03:23:00
【问题描述】:

我目前正在处理 C++ 中的浮点值。 考虑以下 c++ sn-p:

#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 在那种情况下不应该被定义吗?
  • 一般来说,我如何知道我的编译器/架构使用哪种浮点格式?

【问题讨论】:

  • 您使用的是什么编译器版本?我在使用 gcc 6.20 时遇到错误,并且 OS X 上的 clang 给出了isinf(num) = 0

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


【解决方案1】:

isinf,来自cmath 的函数,旨在与C 语言兼容,采用double。您的 long double 参数在传递给该函数时会静默转换为 double。根据浮点舍入规则,转换为double 会产生+inf(任何大于限制的数字本身略大于DBL_MAX 都会舍入为+inf)。

相比之下,std::isinfoverloaded 并且可以采用 long double。当您将 long double 传递给它时,参数不会被转换,std::isinf 可以判断它不是无限的。


尝试回答您的其他问题:

  • isinf 是宏还是函数,这是一个小细节。知道它是一个宏,只方便那些想#undef它的程序员。无论是函数还是保证是宏,它的行为都是一样的(将其参数转换为double)。

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

【讨论】:

  • 对于 C++,std::numeric_limits 通常优于 C 宏,并且可以扩展到可能出现的其他浮点类型。
  • "isinf, ...采取双倍。" 不清楚。至少在 C 中,它是 int isinf(real-floating x) 也许这与 语义类型 的含义有关,“首先,以比其语义类型更宽的格式表示的参数被转换为其语义类型” C11 7.12.3.3 2
  • @Bob__ 抱歉,您似乎不小心在我的回答下发布了您对问题的评论
猜你喜欢
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-03
  • 2015-12-12
  • 2017-05-20
  • 2019-08-08
相关资源
最近更新 更多