在需要处理sin(x)/ x函数的程序中,我遇到了NAN问题,我在以下代码中简化了问题:
#include <iostream>
#include <cmath>
int main()
{
std::cout.precision(15);
//This line compiles and run in g++, but does not compile in Visual Studio 2013
std::cout << 0.0/0.0 << std::endl;
//This line compiles and run in both g++ and VS2013
std::cout << std::sin(0.0)/0.0 << std::endl;
return 0;
}
在g ++中,输出为:-nan -nan,在VS2013中,输出为:-1.IND,因为第一行没有编译所以我将其注释掉了。
我的问题是:
这个'-1.IND'是什么意思?
似乎NAN处理依赖于编译器,这应该在C ++中标准化吗?为什么呢?
我用这个黑客来处理这个问题:
double sinc(double x)
{
if(x == 0.0)
return 1.0;
return std::sin(x)/x;
}
这是正确的方法吗?
编辑:另一个问题,4。为什么VS2013处理0.0 / 0.0和sin(0.0)/0.0不同?
答案 0 :(得分:12)
你的回答也有类似的问题:
1.这是什么&#39; -1.IND&#39;意思?
请参阅What do 1.#INF00, -1.#IND00 and -1.#IND mean?
2.似乎NAN处理依赖于编译器,这应该在C ++中标准化吗?为什么呢?
请参阅A few things about division by zero in C(它说的是C,但它谈到的是C ++)
3.我用这个黑客来处理这个问题:
double sinc(double x) { if(x == 0.0) return 1.0; return std::sin(x)/x; }
这是正确的方法吗?
是的,sinc函数的这种实现将起作用(感谢@MSalters的评论)在数学上是正确的;但是,请记住,虽然它适用于此案例,但不要养成将double
类型与==
进行比较的习惯。
答案 1 :(得分:5)
要为(4)添加答案,sin(x)
是运行时函数,因此sin(0.0)/0.0
作为在运行时计算的表达式处理。 OTOH,0.0/0.0
由编译器完全处理,这就是它发现问题的原因。 Visual Studio版本的实现细节,而不是可以计算的内容。
答案 2 :(得分:3)
在C和C ++标准中,完全符合IEEE浮点标准是可选。这是因为,由于我从未清楚过的原因,CPU设计人员讨厌 IEEE浮点标准。我不知道任何 CPU正确有效地实现了整个规范。 (据我所知,你可以拥有的最好的CPU是一个对正常有限数字来说快速且正确的CPU,但如果你想使用非正规数,无穷大和NaN,它会遭受多次数量级的减速。)
C和C ++标准由编译人员编写。编译人员希望能够生成在真实CPU上快速运行的机器代码,并且他们知道真正的CPU会在IEEE浮点上偷工减料,因此他们不能将完整的IEEE浮点符合性作为语言要求。
答案 3 :(得分:2)
double res = 0.0 / 0.0
的编译失败,因为编译器试图优化它确定的代码&#34;无效&#34;表达。它无法优化sin(x) / 0.0
之类的表达,因为它无法简化和优化&#34;像这样的代码&#34;。double
数据类型的特殊值取决于平台。但表示依赖于架构。要检查这一点,您可以在不同的体系结构上运行此功能:
template<typename T>
void inspect(T v1, T v2)
{
T i_val = v1;
i_val /= v2;
size_t len = sizeof(T);
int* bit_repr = (int*)(&i_val);
for (int i = 0; i < (len / sizeof(int)); i ++)
{
std::bitset<sizeof(int) * 8> bs(*(bit_repr + i));
std::cout << bs;
}
std::cout << std::endl;
}
使用以下参数调用上一个函数:
inspect<double>(0.0, 0.0);
inspect<double>(1.0, 0.0);
inspect<double>(-1.0, 0.0);
答案 4 :(得分:1)
这可能会有所帮助: C ++ 11(所以VS2013)有一些功能可以理解给定的数字是NAN还是有限的。 使用std :: isnan()或std :: isfinite()