浮點數的上溢下溢


---------------------------------------------

原引C Primer Plus (sixth edition)對浮點值上溢下溢的解釋:

假設系統最大的float類型值是3.4E38,編寫如下代碼:

float toobig = 3.4E38 * 100.0f;
printf("%e\n",toobig);

會發生什么呢?這是一個上溢(overflow)的示例。當計算導致數字過大,超過當前類型能表達的范圍時,就會發生上溢。這種行為在過去是未定義的,不過現在C語言規定,在這種情況下會給toobig賦一個表示無窮大的特定值,而且printf()顯示該值為inf或infinity(或者具有無窮含義的其他內容)①。

 

當初以一個很小的數時,情況更為復雜。回憶一下,float類型的數以指數和尾數部分來儲存②。存在這樣一個數,它的指數部分是最小值,即由全部可用位表示的最小尾數值。該數字是float類型能用全部精度表示的最小數字。現在把它除以2。通常,這個操作會減小指數部分,但是假設的情況中,指數是最小值了,所以計算機只好把尾數部分的位向右移,空出1個二進制位,並丟棄最后一個二進制數。以十進制為例,把一個4位有效數字的數(如,0.1234E-10)除以10,得到的結果是0.123E-10.雖然得到了結果,但是在計算過程中卻損失了原本尾有效位上的數字。這種情況叫做下溢(underflow)。C語言把損失了類型全精度的浮點值稱為低於正常的(subnormal)浮點值。因此,把最小的正浮點數除以2將得到一個低於正常的值。如果除以一個非常大的值,會導致所有位都為0。現在,C庫已提供了用於檢查計算是否會產生低於正常值的函數。

還有另一個特殊的浮點值NaN(not a number的縮寫)。例如,給asin()函數傳遞一個值,該函數將返回一個角度,該角度的正弦就是傳入函數的值。但是正弦值不能大於1,因此,如果傳入參數大於1,該函數的行為是未定義的。在這種情況下,該函數將返回NaN值,printf()函數可將其顯示為nan,Nan或其他類似的內容。

-----------------------------------------

解釋:

①運行上述代碼的結果(使用TDM-GCC 4.9.2編譯):1.#INF00e+000

②float類型的數以指數和尾數部分來儲存:例如以浮點形式存儲π,內存中大致如下[+][ .314159 ][ 1 ],即[符號][尾數][指數]

通常情況下,上溢是在對數進行加法時發生的,下溢是在對數進行除法時發生的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM