33 浮點數不是真實的

2021-06-18 10:41:05 字數 1346 閱讀 6565

數學角度中,浮點數並不是「實數」,儘管它們在某些程式語言中叫實型資料,比如pascal和fortran。實數有著無限的精度因而是持續的、無損的;浮點數只有有限的精度,所以它們是有限的,像是「表現異常」的整數,因為他們沒有在範圍內均勻分布。

舉個例子,分配2147483647(最大的32位有符號整數)給乙個32位float變數(記為x),列印它,你會看到2147483648。再列印x - 64,仍是2147483648。然後列印x - 65,你會得到2147483520!為什麼?因為在那個範圍的相鄰浮點數之間的間隔是128,而且浮點操作會近似到(類似四捨五入)最近的浮點數。

ieee浮點數精度是固定的,基於以2為底的科學計數法:1.dd2...dp-1× 2e

,其中p是精度(float是24,double是53)。連續的兩個數字之間的間隔是21-p+e

,可以安全地近似為 ε|x|,其中ε是機器精度(21-p)。

了解了相鄰浮點數之間的間隔,可以幫助你避免經典的數字錯誤。比如,你正在進行迭代計算,例如查詢方程根,要求比數字系統能給的相鄰結果的精度更高的精度,是沒道理的。確保你要求的寬度差不少於相鄰數字的間隔,否則就死迴圈了。

既然浮點是實數的近似,那麼免不了會有點誤差表現。這個誤差,即所謂的捨入誤差,可能導致令人驚訝的結果。如果你把相近的數字相減,比如,最高有效數字抵消了,最低有效位(捨入誤差存在的位)在浮點數結果中公升到了最高有效位,任何相關的計數基本上都被破壞了(這就是稱為「抹除」,smearing的現象)。你需要在演算法中仔細檢查以避免此類的巨量消失。舉例來說,考慮使用二次公式解方程 x2 - 1000x + 1 =0。由於表示式 -b + sqrt(b2 -4) 中各運算元的量值幾乎相等,你可以計算  r1

= -b - sqrt(b2

- 4),然後代入 r2

= 1/r1

,因為對於二次方程 ax2

+ bx + c = 0,兩個根滿足 r1

r2 = c/a。

抹除可能以更加微妙的方式發生。假設乙個庫通過公式1 + x + x2

/2 + x3

/3! + .... 天真地計算ex

。這對正數x是有效的,但是想一下x是很大的負數時會發生什麼。偶數次的條目會產生巨大的正數,減去奇數次的量值不會影響結果。這裡的問題是大的正數條目的捨入誤差在乙個比真正答案更高的有效位上。結果會發散到正無窮!解決方法也很簡單,對於負數x,計算ex

= 1/e|x|

。不言而喻,你不應該在金融應用程式中用浮點數——那正是python、c#等語言中的小數型的用處。浮點數的目的是高效的科學計算,但是不精確的話,高效也沒有意義,所以請記住捨入誤差的根源並相應地編碼!

原文:floating-point numbers aren't real

bychuck allison 

浮點數的儲存以及 浮點數的比較

浮點數的儲存採用的是近似的原理 float儲存格式為 s e m 1位符號位 8位指數 23位尾數 轉成數值即為 v 1 s 1.m 2 e 127 對於16.5轉成二進位制為00010000.1 1.00001 2 4,那麼在記憶體的表示為 符號位 指數4 127 131 尾數 0 1000001...

浮點數 儲存

關鍵字 體系結構 ieee754 浮點數 儲存 main 如果不執行上面的 讓我們來直接判斷,輸出的結果會是什麼?而在你執行程式之後,結果卻很讓人詫異 123.456001。為什麼會是123.456001?有六位小數可以理解,最後那個1是為何?有很多人解釋說最後那個1是亂碼,隨機的。嘿嘿 其實無論你...

浮點數操作

float fx 49.03f int nx fx 100 printf d nx 執行上述 結果 4902。用vc6.0,2005,gcc編譯執行結果都是一樣。為什麼會這樣呢,是因為浮點數運算具有不精確性。其實編譯上面的 編譯器會有警告的。warning c4244 initializing co...