浮点格式和 isinf()
Floating point formats and isinf()
我目前正在处理 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, this creates an 80 bit extended precision 浮点值,因为我在 x86 机器上使用 GCC。因此,浮点值是 0xcccc cccc cccc cccc cccc
并且应该是有效值。
有趣的是,输出如下:
num = -4.77987e+986
isinf(num) = 1
std::isinf(num) = 0
这让我想知道:
- 为什么
isinf
和 std::isinf
的行为不同?哪一个值得信任?
- Here说在C99中,isinf是一个宏,而在C++11中,它变成了一个函数。但是,当我编译示例时,例如使用
-std=c++98
,我仍然得到相同的行为。 std::isinf
在那种情况下甚至不应该被定义吗?
- 一般来说,我如何知道我的 compiler/architecture 使用哪种浮点格式?
isinf
,来自 cmath
的函数,旨在与 C 语言兼容,采用 double
。当传递给该函数时,您的 long double
参数会自动转换为 double
。转换为 double
会根据浮点舍入规则生成 +inf
(任何大于限制的数字本身略大于 DBL_MAX
会被舍入为 +inf
)。
相比之下,std::isinf
是overloaded,可以取一个long double
。当你传递给它一个 long double
时,参数不会被转换并且 std::isinf
可以告诉它它不是无限的。
尝试回答您的其他问题:
isinf
是宏还是函数是一个小细节。知道它是一个宏只是方便那些想要#undef
它的程序员。无论是函数还是保证是宏,它的行为都是一样的(将其参数转换为double
)。
DBL_MAX
和 LDBL_MAX
来自 float.h
/cfloat
足以指示区分 IEEE 754 双精度(64 位格式)或扩展的 80 位格式。您还可以查看其他宏,例如 DBL_MANT_DIG
和 LDBL_MANT_DIG
,如果您想要确定您的代码在 20 年内识别四精度时广泛的处理器实现它(这不是2017 年的案例)。不建议查看 sizeof(long double)
,因为对于 80 位浮点格式,此值可以是 10、12 或 16,具体取决于编译器填充它的程度,值 16 也可以表示四精度.
我目前正在处理 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, this creates an 80 bit extended precision 浮点值,因为我在 x86 机器上使用 GCC。因此,浮点值是 0xcccc cccc cccc cccc cccc
并且应该是有效值。
有趣的是,输出如下:
num = -4.77987e+986
isinf(num) = 1
std::isinf(num) = 0
这让我想知道:
- 为什么
isinf
和std::isinf
的行为不同?哪一个值得信任? - Here说在C99中,isinf是一个宏,而在C++11中,它变成了一个函数。但是,当我编译示例时,例如使用
-std=c++98
,我仍然得到相同的行为。std::isinf
在那种情况下甚至不应该被定义吗? - 一般来说,我如何知道我的 compiler/architecture 使用哪种浮点格式?
isinf
,来自 cmath
的函数,旨在与 C 语言兼容,采用 double
。当传递给该函数时,您的 long double
参数会自动转换为 double
。转换为 double
会根据浮点舍入规则生成 +inf
(任何大于限制的数字本身略大于 DBL_MAX
会被舍入为 +inf
)。
相比之下,std::isinf
是overloaded,可以取一个long double
。当你传递给它一个 long double
时,参数不会被转换并且 std::isinf
可以告诉它它不是无限的。
尝试回答您的其他问题:
isinf
是宏还是函数是一个小细节。知道它是一个宏只是方便那些想要#undef
它的程序员。无论是函数还是保证是宏,它的行为都是一样的(将其参数转换为double
)。DBL_MAX
和LDBL_MAX
来自float.h
/cfloat
足以指示区分 IEEE 754 双精度(64 位格式)或扩展的 80 位格式。您还可以查看其他宏,例如DBL_MANT_DIG
和LDBL_MANT_DIG
,如果您想要确定您的代码在 20 年内识别四精度时广泛的处理器实现它(这不是2017 年的案例)。不建议查看sizeof(long double)
,因为对于 80 位浮点格式,此值可以是 10、12 或 16,具体取决于编译器填充它的程度,值 16 也可以表示四精度.