2

I'm writing a program that uses a very long recursion (about 50,000) and some very large vectors (also 50,000 in length of type double) to store the result of each recursion before averaging them. At the end of the program, I expect to get a number output.

However, some of the results I got was "nan". The mysterious thing is, if I reduce the number of recursions the program will work just fine. So I'm guessing this might be something to do with the size of the vector. So my question is, if you get an overflow in a very long vector (or say array), what will be the effect? Will you get an "nan" just like in my case?

Another mysterious thing about my program is that I have tried some even larger recursions (100,000), but the output was normal. But when I changed a parameter value, so that each numbers stored in the vector will become larger (although they are still of type double), the output becomes "nan". Will the maximum capacity of a vector be dependent on the size of the number it stores?

Vokram
  • 2,097
  • 4
  • 19
  • 27
  • The size represented by the `double` values in your vector has nothing to do with its capacity, and the length of your vector has nothing to do with NaNs appearing. I wouldn't be surprised if you are having problems with uninitialised values elsewhere. – paddy Oct 07 '12 at 13:01

2 Answers2

3

You didn't tell us what your recursion is, but it is fairly easy to generate NaNs with a long sequence of operations if you are using square root, pow, inverse sine, or inverse cosine.

Suppose your calculation produces a quantity, call it x, that is supposed to be the sine of some angle θ, and suppose the underlying math dictates that x must always be between -1 and 1, inclusive. You calculate θ by taking the inverse sine of x.

Here's the problem: Arithmetic done on a computer is but an approximation of the arithmetic of the real numbers. Addition and multiplication with IEEE floating point numbers are not transitive. You might well get a value of 1.0000000000000002 for x instead of 1. Take the inverse sine of this value and you get a NaN.

A standard trick is to protect against those near misses that result from numerical errors. Don't use the built-in asin, acos, sqrt, and pow. Use wrappers that protects against things like asin(1.0000000000000002) and sqrt(-1e-16). Make the former pi/2 rather than NaN, and make the latter zero. This is admittedly a kludge, and doing this can get you in trouble. What if the problem is that your calculations are formulated incorrectly? It's legitimate to treat 1.0000000000000002 as 1, but it's best not to treat a value of 100 as if it were 1. A value of 100 to your asin wrapper is best treated by throwing an exception rather than truncating to 1.

There's one other problem with infinities and NaNs: They propagate. An Inf or NaN in one single computation quickly becomes an Inf or a NaN in hundreds, then thousands of values. I usually make the floating point machinery raise a floating point exception on obtaining an Inf or NaN instead of continuing on. (Note well: Floating point exceptions are not C++ exceptions.) When you do this, your program will bomb unless you have a signal handler in place. That's not necessarily a bad thing. You can run the program in the debugger and find exactly where the problem arose. Without these floating point exceptions it is very hard to find the source of the problem.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
2

Depends on the exact natur of your computations. If you just add up numbers which aren't NaN, the result shouldn't be NaN, either. It might be +infinity, though.

But you will get NaN if e.g. some part of your computation yields +infinity, another -infinity, and you later add those two results.

Assuming that your architecture conforms to IEEE 754, this http://en.wikipedia.org/wiki/NaN#Creation tells the situations in which arithmetic operations return NaN.

fgp
  • 8,126
  • 1
  • 17
  • 18
  • Can you add up very large "normal" numbers to become infinity? – Vokram Oct 07 '12 at 13:11
  • @Vokram Yes. If the sum isn't representable as a floating-point number, the value becomes infinity instead. – fgp Oct 07 '12 at 13:13
  • How big would that need to be? I read the wiki post but I still can't find any division by zero or $\sqrt{-1}$ in my program... – Vokram Oct 07 '12 at 13:23
  • @Vokram Depends on the floating point type you use, but in general, big. You should be able to find the exact limits of your floating point type by googling around. – fgp Oct 07 '12 at 13:37