關于C語言除0引發(fā)的思考
<SPAN style="BACKGROUND-COLOR: rgb(241,254,221)">
<SPAN style="FONT-FAMILY: Microsoft YaHei">
進行浮點數(shù)編程時,如果沒有注意,常常會出現(xiàn)輸出類似 1.#IND, 1.#INF 或者 nan, inf 之類奇怪的輸出。這通常隱含了浮點數(shù)操作的異常。
</SPAN></SPAN>
進行整數(shù)除0的時候,程序會檢查出一個錯誤,比如對于這個代碼:
#include <stdio.h>
#include <math.h>
int main()
{
int m;
m=1/0;
printf("%d",m);
return 0;
}
運行完以后程序就會警告:warning: division by zero [-Wdiv-by-zero]
但是對于浮點數(shù),就沒有類似的檢查:
#include <stdio.h>
#include <math.h>
int main()
{
double m;
m=1.0/0.0;
printf("%lf",m);
return 0;
}
不會有警告或者報錯,但是運行完以后會出現(xiàn)這樣的值:-1.#IND00,不知所云。于是上網(wǎng)查了一下,原來是這樣!
特殊浮點數(shù)的含義
1.#INF / inf:這個值表示“無窮大 (infinity 的縮寫)”,即超出了計算機可以表示的浮點數(shù)的最大范圍(或者說超過了 double 類型的最大值)。
例如,當用 0 除一個整數(shù)時便會得到一個1.#INF / inf值;相應的,如果用 0 除一個負整數(shù)也會得到 -1.#INF / -inf 值。 -1.#IND / nan:這個的情況更復雜,一般來說,它們來自于任何未定義結果(非法)的浮點數(shù)運算。"IND"是 indeterminate 的縮寫,而"nan"是 not a number 的縮寫。產(chǎn)生這個值的常見例子有:對負數(shù)開平方,對負數(shù)取對數(shù),0.0/0.0,0.0*∞, ∞/∞ 等。 簡而言之,如果遇到 1.#INF / inf,就檢查是否發(fā)生了運算結果溢出除零,而遇到 1.#IND / nan,就檢查是否發(fā)生了非法的運算。
特殊浮點數(shù)的判斷
很多 C 庫都提供了一組函數(shù)用來判斷一個浮點數(shù)是否是無窮大或 NaN。int _isnan(double x) 函數(shù)用來判斷一個浮點數(shù)是否是 NaN,而 int _finite(double x) 用以判斷一個浮點數(shù)是否是無窮大。
你可能已經(jīng)注意到了,上面兩個函數(shù)都是以下劃線開頭的,因此在可移植性上可能是存在問題的,那么如何實現(xiàn)一個通用的判斷版本呢?
首先,對于 Nan,可以用下面的代碼實現(xiàn):
bool IsNumber(double x)
{
// 這里的比較操作看上去總是會得到 true
// 但有趣的是對于 IEEE 754 浮點數(shù) NaN 來說總會得到 false!
return (x == x);
}
而下面的代碼可以判斷一個浮點數(shù)是否是有限的(finite, 即既不是 NaN 又不是 infinite):
bool IsFiniteNumber(double x)
{
return (x <= DBL_MAX && x >= -DBL_MAX);
}
其中,DBL_MAX 是 <float.h> 中預定義的常量。
把上面兩個函數(shù)結合起來,還可以實現(xiàn)一個浮點數(shù)是否是 Inf 的判斷。