float為什麼不能直接用 作比較

2021-08-14 08:39:17 字數 2694 閱讀 4726

origin:浮點格式是一種資料結構,用於指定包含浮點數的字段,這些欄位的布局及其算術解釋。自計算機發明以來,出現了許多種不同的浮點數表達方式,目前最通用的是ieee二進位制浮點數算是標準-ieee 754.

ieee 754規定了四種表示浮點數值的方式:單精確度(32位)、雙精確度(64位)、延伸單精確度(43位元以上,很少使用)與延伸雙精確度(79位元以上,通常以80位實現)。只有32位模式有強制要求,其他都是選擇性的。大部分程式語言都有提供ieee浮點數格式與算術,但有些將其列為非必需的。例如,ieee 754問世之前就有的c語言,現在有包括ieee算術,但不算作強制要求(c語言的float通常是指ieee單精確度,而double是指雙精確度)。

所有的資料在計算機內都已二進位制形式表示,那麼浮點數的在計算機內是如何以二進位制形式儲存的呢?

二進位制浮點數是以符號數值表示法的格式儲存——浮點數由三部分組成:符號(sign部分,表示符號0正,1負數),指數(exponent部分,表示指數字),和尾數(fraction部分,表示有效數字,大於等於1,小於2)。

單精度浮點數來說,sign佔1位,exponent部分佔8位,fraction部分佔23位。

雙精度浮點數來說,sign佔1位,exponent部分佔11位,fraction部分佔52位。

那麼該如何理解上面這段話呢?舉例來說,十進位制的5.0,寫成二進位制是101.0,相當於1.01×2^2。那麼,按照上面那段話,可以得出符號位sign為0,fraction部分為1.01,exponent部分為2。

先介紹一下轉換採用的規則:

二進位制轉十進位制規則:

r進製轉換成十進位制:基數為r的數字,只要將各個數字與它的權相乘,其積相加,和數就是十進位制數。

十進位制轉二進位制規則:

整數部分:正整數轉成二進位制。要點一定一定要記住哈:除二取餘,然後倒序排列,高位補零。

小數部分:小數部分的轉換規則:十進位制小數轉換成二進位制小數採用"乘2取整,順序排列"法。具體做法是:用2乘十進位制小數,可以得到積,將積的整數部分取出,再用2乘餘下的小數部分,又得到乙個積,再將積的整數部分取出,如此進行,直到積中的小數部分為零,如果得不到零就擷取達到所要求的精度就可以。 然後把取出的整數部分按順序排列起來,先取的整數作為二進位制小數的高位有效位,後取的整數作為低位有效位。

例1: 把二進位制數110.0101轉換為十進位制數:

110.0101=12^2+121+0*20+02^(-1)+12(-2)+0*2(-3)+1*2^(-4)=6.3125

例2: 把十進位制數8.125轉換成二進位制數:

整數部分:

13 = 1000,

小數部分:

0.125x2 = 0.25, 整數字是0->1000.0;

0.25x2 = 0.5, 整數字是0->1000.00;

0.5x2 = 1, 整數字是1->1000.001;

所以8.125 轉換成二進位制是1000.001

例3: 把十進位制數0.1轉換為二進位制數。

0.1x2 = 0.2, 整數字是0 -> 0.0;

0.2x2 = 0.4, 整數字是0 -> 0.00;

0.4x2 = 0.8, 整數字是0 -> 0.000;

0.8x2 = 1.6, 整數字是1 -> 0.0001;

0.6x2 = 1.2, 整數字是1 -> 0.00011;

0.2x2 = 0.4, 整數字是0 -> 0.000110;

...

得到乙個無限迴圈的二進位制小數,顯然用有限的字長是無法表示0.1的。告訴你乙個悲傷的訊息0.2,0.4,0.6,0.8,0.3,0.7,0.9都是無法精確表示的。只有0.5可以用二進位制精確表示。拿這些無法精確表示的數該怎麼辦呢?我們在十進位制轉二進位制的規則裡說過,如果沒有得到0,就擷取達到所要求的精度就可以。由此可知,乙個十進位制小數要能用二進位制浮點數精確表示,最後一位必須是5.當然這是必要條件,並非充分條件。由此可以看出,乙個十進位制數能否用二進位制浮點數精確便是,關鍵在於小數部分。

不可將浮點變數用「==」或「!=」做直接比較,而應該設法轉化成能用「>=」或「<=」作比較的形式。由上可知計算機在處理浮點數的時候是有誤差的,所以判斷兩個浮點數是不是相同,是要判斷是不是落在同乙個區間的,這個區間就是 [-epsinon,epsinon] epsinon一般很小,10的-6次方以下,這個值肯定是越小越精確,不過也看具體的個情況,夠用就好。

float與「零值」比較

一般情況我們會定義乙個很小的接近於0的值比如0.00001或者更小的,然後浮點數跟這個數作比較。

假設x是乙個浮點數:

const float epsinon = 0.00001;

if ((x >= - epsinon) && (x <= epsinon)

或者if( abs(a-b) < flt_epsilon)

float與float比較

假設x,y是兩個浮點數是否相等:

const float epsinon = 0.00001;

if( abs(a-b) <= epsinon )

還有一種方法就是擴大再取整,比如4.113、4.114,直接比較有可能為 false,但是都擴大一千倍,然後強制轉換為 int 型別,再用 == 比較就可以了。

為什麼float比long型別的資料範圍大

float比long型別的資料範圍大。float 4個位元組 long 8個位元組 為什麼float的4個位元組比long型別的8個位元組的範圍大?因為整數與小數的底層儲存有點不同。相同點 它們都是用二進位制儲存的 不同點 小數先轉成二進位制,然後處理,然後儲存。符號位 其中最左邊的為符號位,0為正...

抽象類為什麼不能直接建立物件?

1.子類更具體,父類更抽象,直接建立父類物件本身沒有意義。2.如果建立的是父類物件再呼叫方法的時候,呼叫的父類中的方法,而非子類的方法,它違背了多型的這種思想和設計 3.因為父類引用指向子類物件時,呼叫的方法是子類重寫的方法,一般父類中的描述不夠具體,並不是說抽象類的構造方法沒有意義,那麼在建立子類...

為什麼 比list()更快?

我最近比較了和list 的處理速度,並且驚訝地發現執行速度比list 快三倍以上。我跑了相同的測試與 和dict 結果幾乎相同 和 兩個花了大約0.128sec 百萬次,而list 和dict 大約花費每個0.428sec 萬次。後來我查了查原因,得到的結論如下 list 需要全域性查詢和函式呼叫,...