浮點數的大小比較為什麼不能用等號?

2022-03-27 00:54:49 字數 2362 閱讀 2138

前些天參加深信服面試,面試官問了這樣乙個問題:浮點數的大小比較為什麼不能用等號?那時就沒回答好,因為自己一直把「浮點數大小比較不能夠用等號」當做預設事實而沒有去深究其背後原理。本文將試著解釋這個事實。

計算機中是如何儲存和表達數字的?對於整數,情況比較簡單,直接按照數學中的進製轉換方法處理即可,即連續除以2取餘。這並不是難點,真正的難點在於小數是如何轉換為二進位製碼(即浮點數)的(注意區別小數和浮點數)。

當然,從數學的角度來講,十進位制的小數可以轉換為二進位制小數(整數部分連續除2,小數部分連續乘2),例如125.125d=1111101.001b,但問題在於計算機根本就不認識小數點「.,更不可能認識1111101.001b。那麼計算機是如何處理小數的呢?

歷史上計算機科學家們曾提出過多種解決方案,最終獲得廣泛應用的是ieee 754標準中的方案,目前最新版的標準是ieee std 754-2008。該標準提出數字系統中的浮點數是對數學中的實數(小數)的近似,同時該標準規定表達浮點數的0、1序列被分為三部分(三個域):

以32位單精度浮點數為例,其具體的轉換規則是:首先把二進位制小數(補碼)用二進位制科學計數法表示,比如上面給出的例子1111101.001=1.111101001*2^6。符號位sign表示數的正負(0為正,1為負),故此處填0。exponent表示科學計數法的指數部分,請務必注意的是,這裡所填的指數並不是前面算出來的實際指數,而是等於實際指數加上乙個數(指數偏移),偏移量為2^(e-1)-1,其中e是exponent的寬度(位數)。對於32位單精度浮點數,exponent寬度為8,因此偏移量為127,所以exponent的值為133,即10000101。之後的fraction表示尾數,即科學計數法中的小數部分11110100100000000000000(共23位)。因此32位浮點數125.125d在計算機中就被表示為01000010111110100100000000000000。

對於32位單精度浮點數,sign是1位,exponent是8位(指數偏移量是127,fraction是23位。對於64位雙精度浮點數,sign是1為,exponent是11位(指數偏移量是1023,fraction是52位。

用程式可以看出小數在計算機中是如何表示的(即浮點數):

1 #include 2 #include 3

using

namespace

std;45

intmain()

6

程式執行結果:

下文將從幾個方面來探索這個問題:

請見程式:

1 #include 2 #include 3

using

namespace

std;45

intmain()

6

程式執行結果如下:

從該例子可以看出,對於同乙個小數,當用不同精度表示時,結果是不一樣的,不能直接用等號比較大小。

按照博文計算機中基本型別float值表示和大小比較問題的說法: 

即使在精度相同的情況下,比較也可能會出問題。因為在運算過程中會將記憶體(或快取記憶體)中的值載入到cpu浮點暫存器(80 bit擴充套件精度)中,然後再進入cpu浮點計算單元進行計算,計算結果寫回浮點暫存器,然後寫回記憶體(或快取記憶體)。從記憶體到浮點暫存器,浮點數的精度會擴充套件,從浮點暫存器到記憶體,浮點數的精度會降低(精度擴充套件通常沒問題,但如果精度降低了,很可能值會發生變化,出現截斷),而浮點運算的結果由於下面還要使用所以暫時儲存在浮點暫存器中留待下次使用(沒有及時寫回記憶體,這是一種優化策略),從而導致資料並不是記憶體中和記憶體中的資料比較而是浮點暫存器中的值和記憶體中的值進行比較,而無論記憶體中是float型別還是double型別,其精度和浮點暫存器精度都不相同,從而導致比較結果是不相等。  

詳細的可參考維基百科條目extended precision。

**計算機中浮點數的表達方法(ieee 754)

計算機中基本型別float值表示和大小比較問題

浮點數的大小比較

節選自 浮點數 以c c 為準 一般用的較多的是float,double。佔位元組數 數值範圍 十進位制精度位數 float 4 3.4e 38 3.4e38 6 7double 8 1.7e 308 1.7e308 14 15 如果記憶體不是很緊張或者精度要求不是很低,一般選用double。14位...

為什麼浮點數不能精確表示?

我們知道,在編寫程式時,兩個浮點數 float或double 不能直接進行大小比較。當然,我們也都知道,不能直接進行大小比較的原因是因為浮點數在計算機內部不能精確的表示。可是,為什麼在計算機內部浮點數不能夠精確地表示呢?這還得從ieee 754標準說起。根據ieee 754標準,浮點數在計算機內部儲...

浮點數比較大小的問題

浮點數比較大小,由於精度問題,所以直接比較有時可能會出錯。單精度數7位有效數字。float 雙精度數16位有效數字。double 單精度數的尾數用23位儲存,加上預設的小數點前的1位1,2 23 1 16777216。因為 10 7 16777216 10 8,所以說單精度浮點數的有效位數是7位。雙...