1.#IND 1.#INF nan inf 1.#QNAN SNaN 问题的解决
内容整理自网络
进行浮点数编程时,如果没有注意,常常会出现输出类似 1.#IND, 1.#INF 或者 nan, inf 之类奇怪的输出。这通常隐含了浮点数操作的异常。
特殊浮点数的含义
1.#INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当用 0 除一个整数时便会得到一个1.#INF / inf值;相应的,如果用 0 除一个负整数也会得到 -1.#INF / -inf 值。
-1.#IND / nan:这个的情况更复杂,一般来说,它们来自于任何未定义结果(非法)的浮点数运算。"IND"是 indeterminate 的缩写,而"nan"是 not a number 的缩写。产生这个值的常见例子有:对负数开平方,对负数取对数,0.0/0.0,0.0*∞, ∞/∞ 等。
简而言之,如果遇到 1.#INF / inf,就检查是否发生了运算结果溢出除零,而遇到 1.#IND / nan,就检查是否发生了非法的运算。
特殊浮点数的判断
很多 C 库都提供了一组函数用来判断一个浮点数是否是无穷大或 NaN。int _isnan(double x) 函数用来判断一个浮点数是否是 NaN,而 int _finite(double x) 用以判断一个浮点数是否是无穷大。
你可能已经注意到了,上面两个函数都是以下划线开头的,因此在可移植性上可能是存在问题的,那么如何实现一个通用的判断版本呢?首先,对于 Nan,可以用下面的代码实现:
bool IsNumber(double x)
{
// 这里的比较操作看上去总是会得到 true
// 但有趣的是对于 IEEE 754 浮点数 NaN 来说总会得到 false!
return (x == x);
}
而下面的代码可以判断一个浮点数是否是有限的(finite, 即既不是 NaN 又不是 infinite):
bool IsFiniteNumber(double x)
{
return (x <= DBL_MAX && x >= -DBL_MAX);
}
其中,DBL_MAX 是 <float.h> 中预定义的常量。
把上面两个函数结合起来,还可以实现一个浮点数是否是 Inf 的判断。
转自:http://live.aulddays.com/tech/10/double-float-ind-nan-inf/
This page will answer the following questions.
1.#IND
or 1.#INF
(on Windows) or nan
or inf
(on Linux). What happened?How can I tell if a number is really a number and not a NaN
or an infinity?How can I find out more details at runtime about kinds of NaN
s and infinities?Do you have any sample code to show how this works?Where can I learn more?These questions have to do with floating point exceptions. If you get some strange non-numeric output where you're expecting a number, you've either exceeded the finite limits of floating point arithmetic or you've asked for some result that is undefined. To keep things simple, I'll stick to working with the double
floating point type. Similar remarks hold for float
types.
If your operation would generate a larger positive number than could be stored in adouble
, the operation will return 1.#INF
on Windows or inf
on Linux. Similarly your code will return -1.#INF
or -inf
if the result would be a negative number too large to store in a double
. Dividing a positive number by zero produces a positive infinity and dividing a negative number by zero produces a negative infinity. Example code at the end of this page will demonstrate some operations that produce infinities.
Some operations don't make mathematical sense, such as taking the square root of a negative number. (Yes, this operation makes sense in the context of complex numbers, but a double
represents a real number and so there is no double
to represent the result.) The same is true for logarithms of negative numbers. Both sqrt(-1.0)
and log(-1.0)
would return a NaN
, the generic term for a "number" that is "not a number". Windows displays a NaN
as -1.#IND
("IND" for "indeterminate") while Linux displays nan
. Other operations that would return a NaN
include 0/0, 0*∞, and ∞/∞. See the sample code below for examples.
In short, if you get 1.#INF
or inf
, look for overflow or division by zero. If you get 1.#IND
or nan
, look for illegal operations. Maybe you simply have a bug. If it's more subtle and you have something that is difficult to compute, see Avoiding Overflow, Underflow, and Loss of Precision. That article gives tricks for computing results that have intermediate steps overflow if computed directly.
Next suppose you want to test whether a number is an infinity or a NaN
. For example, you may want to write to a log file print a debug message when a numerical result goes bad, or you may want to execute some sort of alternate logic in your code. There are simple, portable ways to get summary information and more complicated, less portable ways to get more information.
First, the simple solution. If you want to test whether a double
variable contains a valid number, you can check whether x == x
. This looks like it should always be true, but it's not! Ordinary numbers always equal themselves, but NaN
s do not. I've used this trick on Windows, Linux, and Mac OSX. If you ever use this trick, put big bold comments around your code so that some well-meaning person won't come behind you and delete what he or she things is useless code. Better yet, put the test in a well-documented function in a library that has controlled access. The following function will test whetherx
is a (possibly infinite) number.