Reputation: 1033
In a program that needs to process sin(x)/x function, I encountered NAN problem, I simplified the problem in the following code:
#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;
}
In g++, the output is: -nan -nan, in VS2013, the output is: -1.IND, because the first line does not compile so I commented it out.
My questions are:
What does this '-1.IND' mean?
It seems NAN processing is compiler dependent, should this be standardized in C++? Why?
I used this hack to deal with this problem:
double sinc(double x)
{
if(x == 0.0)
return 1.0;
return std::sin(x)/x;
}
Is this the right way?
EDIT: another question, 4. why VS2013 deal with 0.0/0.0 and sin(0.0)/0.0 differently?
Upvotes: 18
Views: 3616
Reputation: 3653
There are similar questions to yours answered on SO:
1.What does this '-1.IND' mean?
See What do 1.#INF00, -1.#IND00 and -1.#IND mean?
2.It seems NAN processing is compiler dependent, should this be standardized in C++? Why?
See A few things about division by zero in C (it says C, but it talks about C++)
3.I used this hack to deal with this problem:
double sinc(double x) { if(x == 0.0) return 1.0; return std::sin(x)/x; }
Is this the right way?
Yes, this implementation of the sinc function will work and (Thanks to @MSalters for the comment) is mathematically correct; however, keep in mind that, while it will work for this case, don't make a habit of comparing double
types with ==
.
Upvotes: 12
Reputation: 140569
Complete conformance to the IEEE floating point standard is optional in the C and C++ standards. This is because, for reasons which have never been clear to me, CPU designers hate the IEEE floating point standard. I am not aware of any CPU that implements the entire specification correctly and efficiently. (The best you can have, as far as I know, is a CPU that's fast and correct for normal finite numbers but suffers multiple-orders-of-magnitude slowdowns if you want to work with denormals, infinity, and NaN.)
The C and C++ standards are written by compiler people. Compiler people want to be able to generate machine code that runs fast on real CPUs, and they know real CPUs cut corners on IEEE floating point, so they don't make full IEEE floating point conformance a language requirement.
Upvotes: 3
Reputation: 96
This might be helpful : C++ 11 (so VS2013) has some feature to understand if a given number is NAN or is finite. Use std::isnan() or std::isfinite()
Upvotes: 1
Reputation: 304
double res = 0.0 / 0.0
fails because compiler tries to optimize the code it determines "invalid" expression. It can't optimize expression like sin(x) / 0.0
because it's not able to simplify and "optimize" code like this".double
data type is platform dependent. But representation is architecture dependent. To check this you can run this function on different architectures:
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;
}
Call previous function with following arguments:
inspect<double>(0.0, 0.0);
inspect<double>(1.0, 0.0);
inspect<double>(-1.0, 0.0);
Upvotes: 2
Reputation: 179799
To add an answer for (4), sin(x)
is a runtime function, and thus sin(0.0)/0.0
is handled as an expression which is evaluated at runtime. OTOH, 0.0/0.0
is handled fully by the compiler, which is why it spots the problem. An implementation detail of your Visual Studio version, and not something on which you can count.
Upvotes: 5