欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

C語言程序開發中,處理浮點數應該注意哪些?

呂致盈2年前15瀏覽0評論

謝邀。

在C語言程序開發中,有時浮點運算是不可避免的,遺憾的是,由于計算機的精度是有限的,所以很多時候C語言程序并不總是能夠精確的存儲和處理浮點數,這也是很多C語言程序盡力使用整型運算代替浮點運算的原因之一。

計算機存儲浮點數的方式與存儲整數的方式有所不同,遇到很長的浮點數時,總不能采用無限制長度的空間存儲吧?事實上,對于計算機中浮點數的存儲,國際上制定過一些標準。這一點可參考我之前的文章。

鑒于C語言程序不能總是精確的表示浮點數,在我們編寫程序時,需要謹記這一特點,否則最終C語言程序可能會產生難以理解的結果。這里將以問答的形式討論C語言程序開發中,涉及的浮點運算基本注意事項。

定義float變量賦值為3.1,為什么使用printf打印出來的是3.0999999?

其實并不總是如此。很多計算機使用二進制表示整數,也使用二進制表示浮點數。我們人類常用十進制表示數字,遺憾的是,十進制能夠精確表示的數字,并不一定也能使用二進制表示精確。

例如在十進制中,分數1/3=0.33333…無數個3,十進制是無法精確表示這一數字的。同樣的道理,0.1也即1/10在二進制中也是無法精確表示的(0.0001100110011…),所以在這種情況下,3.1也就無法精確表示了,而只能使用3.0999999去近似。

使用printf()函數打印3.1,最終顯示到終端的結果主要取決于所使用計算機中二/十進制的轉換仔細程度。實際上,有時我們將一個精確的十進制浮點數轉換為二進制,然后再轉換回十進制,會發現前后兩個數字并不“相等”。

為什么sqrt(144.)得不到正確結果?

小明希望使用C語言math庫的sqrt()函數計算144的平方根,于是他寫出下面這樣的C語言代碼,請看:

但是小明編譯這段C語言代碼并執行后,發現程序輸出的是一串雜數,這是怎么回事呢?

仔細觀察小明的C語言代碼,能夠發現他雖然調用了math庫中的函數,但是卻并沒有包含相應的頭文件“math.h”,這造成的后果是C語言編譯器無法確定sqrt()函數的原型。此時,編譯器只好“猜測”sqrt()的函數原型為:

也即編譯器認為sqrt()函數的返回值為一個整數。如果讀者看了我之前的文章,應該明白計算機存儲整數和浮點數的方式是不同的,因此C語言程序以浮點數的存儲方式解釋整數時,自然是有可能出現不預期的結果的。

如果C語言編譯器處理函數時未發現其原型,一般都會將intf();當作該函數原型。

如何判斷兩個浮點數“相等”?

計算機無法精確表示浮點數,這個特性也影響了C語言程序判斷兩個浮點數是否相等,如果讀者看過我之前的文章,應該清楚在C語言程序中,==運算符是不能用于判斷兩個浮點數是否相等的。

事實上,鑒于C語言程序無法總是準確表示浮點數,在需要判斷兩個浮點數是否“相等”時,通常的做法是判斷這兩個數是否足夠“接近”:

其中epsilon是一個非常小的整數,上述表達式將浮點數a,b足夠接近近似為“相等”。雖說epsilon應該在浮點數表示范圍內足夠小,但是實際開發中,只要能夠滿足實際需要的精度就可以了,“夠用就行”。因此,epsilon也可以是程序員自行設定的閾值。

如何賦值一些特殊值,如NaN(notanumber,不是數字)?

許多平臺都提供了方便處理浮點數值的工具或者函數,比如一些預定義的常數,以及類似isnan()的函數,這些工具要么作為<math.h>中的標準擴展,要么作為<ieee.h>或<nan.h>的非標準擴展。

一般來說,如果某個數字不與自己相等,那么這個數必定是NaN:

不過,應該注意的是,為遵守IEEE的C語言編譯器可能會對這樣的對比代碼優化。還要注意,即使系統中對NaN這樣的特殊數字做了預定義,我們也不能將其與其他數字對比,例如if(x==NaN)就是不合適的代碼,因為NaN不能與數字做比較。

如果開發C語言程序的平臺沒有直接提供類似于NaN這樣的特殊數字,我們可以自行定義它們,例如:

不過應該明白的是,有些編譯器會將上述兩行C語言代碼當作“浮點異常”處理,此時我們將不能得到nan和inf。

對于NaN和inf,還有一點需要清楚的是sprintf()函數的格式輸出,在有些平臺,它能產生類似于“NaN”以及“inf”的字符串。

小結

本節主要介紹了C語言程序開發中,處理浮點數時應注意的事項。因為計算機無法總是精確存儲浮點數,所以處理浮點數和處理整數是有所區別的,如果不清楚這些,很容易寫出有問題的代碼。這里強烈推薦大家閱讀我之前的文章。