CSI III 資訊的表示與處理 數值陷阱 二

2021-06-21 11:14:13 字數 3928 閱讀 7098

談到浮點數,或許你能想到ieee(讀作「eye-triple-eee」)754標準。這個標準的制定是從2023年開始由intel贊助的,在8087設計的同時,8087是一種為8086處理器提供浮點支援的晶元。他們請kahan作為顧問,幫助設計未來處理器浮點標準。並支援kahan加入ieee委員會,後來ieee最終制定的標準非常接近於kahan為intel設計的標準。這樣ieee754標準也就誕生了。

1. 二進位制小數

在理解浮點數之前我們先看下含有小數值的二進位制數字。首先先看下我們所熟悉的十進位制是如何來表示小數的,十進位制表示法所使用的表示形式為:dmdm-1…d1d0.d-1d-2…d-n,其中每個十進位制數di的取值為0~9,這個表示的數值d為:

類似的,我們考慮形如bmbm-1…..b1b0.b-1b-2…b-n-1b-n的表示法,其中每個二進位制數字bi的取值為0或者1,這種表示方法表示的數b定義如下:

2.ieee浮點表示

ieee浮點標準用v=(-1)s×m×2e的形式來表示乙個浮點數。

符號s決定了這個數是負數(s=1)還是正數(s=0),對於數值0的符號作為特殊情況處理。

尾數 m是乙個二進位制小數,它的範圍是1~2-ε,或者是0~1-ε

階碼e的作用是對浮點數加權,這個權重是2的e次冪(可能是負數)

將浮點數的位表示劃分為三個字段,分別對這些值進行編碼:

<1>.乙個單獨的符號位s直接編碼符號s.

<2>.k位的階碼字段exp=ek-1….e1e0編碼階碼e。

<3>.n位小數字段frac=fn-1….f1f0編碼尾數m,並且編碼出來的值也依賴於階碼字段的值是否等於0。

在單精度浮點格式(float)中,s、exp和frac欄位分別為1位,k=8位和n=23位,得到乙個32位的表示。在雙精度浮點格式(double)中,s、exp和frac的值分別為1位、k=11位和n=52位,得到乙個64位的表示。

給定了位表示,根據exp的值,被編碼的值可以分為三種情況。

下面我們討論這三種情況:

(1).規格化

當exp的位模式既不全為0(數值0),也不全為1(單精度數值為255,雙精度數值為2047)時,都屬於這類情況。在這種情況中,階碼字段被解釋為以偏置形式表示的有符號整數。也就是說,階碼的值是e=e-bias,其中e是無符號數,其位表示為ek-1…e1e0,而bias是乙個等於2k-1-1(單精度是127,雙精度是1023)的偏置值。由此產生指數的取值範圍,對於單精度是-126~+127,對於雙精度是-1022~+1023。

對小數字段frac的解釋為描述小數值f,其中0<=f<1,其二進位制表示為0.fn-1…f1f0,也就是二進位制小數點在最高有效位的左邊。尾數定義為m=1+f.我們可以將m看成乙個二進位制表示式為1.fn-1fn-2…f0的數字。

(2)非規格化

當階碼域為全0時,所表示的數就是非規格化形式,在這種情況下,階碼值e=1-bias,而尾數的值是m=f,也就是小數字段的值,不包含隱含的開頭的1.

這裡的階碼值為1-bias而不是簡單的-bias,後面我再介紹這麼設定的原因。

(3).特殊值

最後一類數值是當指階碼全為1的時候出現的。當小數域全為0時,得到的值表示無窮,當s=0時是+∞,或者當s=1時是-∞.當小數域為非零時,結果值被稱為」nan」,即不是乙個數。

可能針對上面的概念描述,你可能還不夠清楚浮點數具體是如何表示的,那麼下面我們看乙個數字例項,在這個例項中我們假定8位的浮點格式,其中有k=4的階碼位和n=3的小數字。那麼偏置bias=24-1-1=7,請看下圖:

上圖只是非負值的浮點格式表示,從0自身開始,最靠近0的是給規格化數。這種格式的非規格數的e=1-7=-6,得到權2e=1/64.小數f的值得範圍是0,1/8,….7/8,從而得到數v的範圍是0~1/64*7/8=7/512.

同時,從上圖中我們可以看到從最大的非規格化數7/512到最小的規格化數8/512的平滑轉變,這就是我們為什麼在非規格化數將e定義為1-bias,而不是-bias.

當階碼增大時,我們就能夠得到更大的規格化的值。當取到最大的規格化數時,階碼e=7,尾數m=1+f=1+7/8=15/8,此時的數值為v=27*15/8=1992/8=240。

通過上面的介紹,你一定熟悉了ieee754是如何進行浮點數的編碼的,下面我們再看乙個使用32位浮點格式來對整數12345進行單精度的浮點數表示的例子:

我們知道了對於32位的單精度浮點數,其符號佔1位,階碼e佔8位,尾數m佔23位。整數12345的二進位制表示為[11 0000 0011 1001],通過將二進位制小數點左移13位。我們得到這個數的規格化表示1.1 0000 0011 1001×213,我們丟棄開頭的1,並在末尾增加10個0,以構造小數字,得到的二進位制表示為[1 0000 0011 1001 0000 0000 00]。為了構造階碼字段,我們用13加上偏置127,得到140,其二進位制為[10001100],最後加上符號位0,我們得到這個數的浮點數二進位制 表示為[010001100 1 0000 0011 1001 0000 0000 00]。我們觀察到整數值12345和單精度浮點值12345.0在位級表示上有下列關係:

我們看到,浮點數尾數部分在整數表示的最高有效位1之前就停止了(這個位就是隱含的開頭的位1),和浮點表示的小數部分的高位是匹配的。

3.捨入

計算機的表示方法限制了浮點數的範圍和精度,浮點運算只能近似地表示實數運算。因此,對於值x,我們一般享用一種系統的方法,能夠找到」最接近的」匹配值x』,它可以用期望的浮點形式表示出來。這就是捨入運算。ieee浮點格式定義了四種不同的捨入方式:

向偶數捨入、向零捨入、向下捨入、向上捨入。

向偶數捨入也稱為向最接近的值捨入,是預設的方式,試圖找到乙個最接近的匹配值。當值是兩個可能結果的之間數值時,其採用的方法是:將數字向上或者向下捨入,使得結果的最低有效數字是偶數。因此,這種方法將1.5和2.5美元都捨入成2美元。

有什麼理由偏向取偶數呢?為什麼不始終把位於兩個可表示的值中間的值都向上捨入呢?假設有這樣的場景:這組方法捨入一組數值,會在計算這些值的平均數中引入統計偏差。我們採用這種捨入得到的一組值得平均值將比這些數本身的平均值略高。相反,如果採用向下捨入,那麼得到的平均值就略低。而向偶數捨入在大多數現實情況中避免了這種統計偏差。在50%的時間裡,它將向下捨入,而在50%的時間裡,它將向上捨入。

4.浮點運算

在浮點運算中,浮點加法不具有結合性。例如,表示式(3.14+1e10)-1e10求值得到0.0—因為捨入,3.14會丟失。另一方面,表示式3.14+(1e10-1e10)得到值3.14.

浮點乘法也遵循通常乘法所具有的許多屬性。當同時由於可能發生溢位,或者由於捨入而失去精度,它不具有結合性。例如,在單精度浮點情況下,表示式(1e20*1e20)*1e-20的值為+∞,而1e20*(1e20*1e-20)將得出1e20.另外,浮點乘法在加法上不具備分配性。例如,在單精度浮點情況下,表示式1e20*(1e20-1e20)的值為0.0,而1e20*1e20-1e20*1e20會得到nan.

5.c語言的浮點數

c語言提供了兩種不同的浮點資料型別:float和double。當int、float和double格式之間進行強制型別轉換時,程式改變量值和位模式的原則如下:

(1)從int 轉換成float,數字不會溢位,但是可能被捨入。

(2)從int 或者float轉換成double,因為dobule有更大的範圍和精度,所以能夠保留精確的數值。

(3)從double轉換成float,因為範圍要小一些,所以值可能溢位為-∞或者+∞,另外,由於精度較小,它還可能被捨入。

(4)從float或者double轉換成int,值將會向零捨入。

壹 資訊的表示和處理

道生一,一生二,二生三,三生萬物。萬物始於此,此為何物?從基本資料型別開始,我們將逐漸深入了解計算機。計算機為什麼用二進位制?對於十個手指的人來說,使用十進位制是自然而然的事。但是對於機器來說,使用二進位制有什麼好處?因為二進位制更容易表示,儲存,傳輸 這就要從模擬電路講起,一言以蔽之就是,位元這種...

資訊的表示 二

編寫c語言的 時常見的問題之一就是不同字長的整數相互轉換直接容易引發潛在的錯誤。例如低字長整數轉換為高字長整數會發生隱式位擴充套件,而高字長整數轉換為低字長整數會發生隱式位截斷。可能你會疑惑為什麼這裡只有整數而沒有浮點數,這是因為浮點數在位模式上採用了與整數不同的表示方式,這在之後會討論。在對整數進...

資訊的表示 一

現代計算機儲存和處理的資訊均以二值訊號表示。對於人來說,十進位制已經完全夠了,但對於計算機來說,二進位制會表現得更好,為什麼可以參考 從編碼到二進位制 一文。不同的數字有著不同的含義,這個含義是我們人去定義的,計算機如何理解,需要人去告訴它。對於不同的程式語言,計算機會有不同的理解方式。在此我們主要...