1. 程式人生 > >11、定點數和浮點數

11、定點數和浮點數

1.0 完全 偏移量 壓縮 浪費 平方根 整數加法 內部 二進制表示

我們平時都會用到小數,通常我們可以把小數表示成10的冪的形式,如12.21=1x101+2x100+2x10-1+1x10-2。但是有一些很難表示,如1/3.

小數用二進制表示的最簡單的方法是BCD碼,這在表示錢的時候特別有用。

技術分享圖片

通常把兩個BCD數字存放在一個字節,這種方式成為壓縮BCD。由於2的補數不和BCD數一起使用,因此壓縮BCD通常需要增加1位用來標識數的正負,該位被稱做符號位。用一整個字節保存某個特定的BCD數是很方便的,但要為這個短小的符號位犧牲4位或8位的存儲空間。

看個例子,假設計算機程序所要處理的錢款數目在+/-100萬之間,這就意味著範圍是-9999999.99~99999999.99,因此保存在存儲器中的每一筆錢的金額都需要5個字節。因此,-4325120.25可以表示為下面的5個字節:

00010100 00110010 01010001 00100000 00100101

轉換成十六進制,可等價的表示成:14h 32h 51h 20h 25h

最左邊的1用來表示該數是負數,符號位。

這種基於二進制的存儲和標記方式稱為定點格式,指小數點的位置總是在數的某個特定位置——在本例中,它位於兩位小數之前。

小數點位置的計數信息並沒有和整個數字一起存儲,所以使用小數的程序必須知道小數點的位置。

但是如果很大的數字用這種方式來存儲,就很浪費空間了。

科學家喜歡用科學計數法來表示這類數字,如490000000000可記為4.9x1011,而0.00000000026可以表示為2.6x10-10。4.9、2.6被稱作有效數,11、-10被稱作指數。一般規定有效數的取值範圍大於等於1小於10.

計算機中,對於小數的存儲方式,除了定點格式外還有另外一種選擇,稱為浮點格式。因為浮點格式是基於科學計數法的,它是存儲極大或極小數的理想方式。但計算機中的浮點格式是借助二進制數實現的科學計數法形式,因此我們首先要了解如何用二進制表示小數。

十進制中,小數點右邊的數字與10的負整數次冪相關聯;而在二進制數中,二進制小數點右邊的數字和2的負整數次冪相關。如101.1101可以轉換成1x22+0x21+1x20+1x2-1+1x2-2+0x2-3+1x2-4。觀察下負整次冪,可以發現都是從1開始反復除2得到下一位。如2-1=>0.5,2-2=>0.25,2-3=>0.125,2-4=>0.0625。同十進制一樣,一般有效數大於等於1且小於10(十進制2),如101.1101=》1.011101x22

,可以發現,每次小數點左邊都是1,沒其他數字。

IEEE浮點數標準定義了兩種基本的格式:以4個字節表示的單精度格式和以8個字節表示的雙精度格式。

首先了解下單精度格式。它的4個字節可以分為三個部分:1位的符號位(0代表正數,1代表負數),8位用做指數,最後的23位用做有效數。下面給出了單精度格式的三部分的劃分方式,其中有效數的最低位的最右邊。

技術分享圖片

三部分共32位,小數點最左邊的1並沒有存儲,因為它總是1。盡管存儲只有23位有效數,但仍然稱其精度為24位。

8位指數部分的取值範圍是0~255,稱為偏移指數,它的意思是:對於有符號指數,為了確定其實際所代表的值必須從指數中減去一個值——稱做偏移量。對於單精度浮點數,其偏移量為127。

指數0和255用於特殊的目的,後面介紹。如果指數的取值範圍是1~254,那麽對於一個特定的數,可以用s(符號位),e(指數)以及f(有效數)來描述它:(-1)sx1.fx2e-127

1.f,小數點後面跟著23位有效數。1.f與2的冪相乘,其中指數等於內存中的8位偏移指數減去127。

目前我們需要表達“0”。這是一種特殊情況,下面對其進行說明:

·如果e=0且f=0,則該數為0.在這種情況下,通常把32位都設置為0以表示該數為0.但是符號位可以設置為1,這種數可以解釋為負0.負0可以用來表示非常小的數,這些數極小以至於不能再單精度格式下用數字和指數來表示。但它仍然小於0.

·如果e=0,且f不等於0,則該數是合法的,但不是規範化的。可以表示為(-1)sx0.fx2-127。註意,在有效數中,小數點左邊是0.

·如果e=255且f=0,則該數被解釋為無窮大或無窮小。取決於符號位s的值。

·如果e=255且f不等於0,則該值被解釋為“不是一個數”,通常被縮寫為NaN。NaN用來表示位置的數或非法操作的結果。

單精度浮點格式下,可以表示的規格化的最小正、負二進制數是:

1.00000000000000000000000x2-126,小數點後面跟著23個二進制0.單精度浮點格式下,可以表示規格化的最大正、負二進制數是:

1.11111111111111111111111x2127,在十進制下,這兩個數近似地等於1.175494352x10-38和3.402823466x1038,也就是單精度浮點數的有效表示範圍。

如前所述,10位二進制數可以近似的用3位十進制數來表示。其含義是,如果把10位都置1,即十六進制的3FFh或十進制的1023,它近似等於把十進制的3位都置為9,即999,可以表示為下面的約等式:210=103

兩者關系以為這,單精度浮點數格式存放的24位二進制數大體上與7位十進制數相等,因此,可以說單精度浮點格式提供24位的二進制精度或7位十進制精度。精度大概是1/224,或者百萬分之六

如果用單精度浮點數來存放262144.00元和262144.01元,可以發現在計算機存儲為同一個數:

1.00000000000000000000000x218,這就是人們在處理錢的時候更願意用定點數的一個原因。

也會有一些崩潰的問題,如果你程序進行了一系列計算,應該得到的結果為3.5,由於使用浮點數,你得到的可能是3.499999999999。這種問題在浮點數運算中經常發生,而且沒有一套完整的解決方案。

要解決上面問題,你可以考慮使用雙精度浮點數,這種類型需要8個字節來表示,結構如下:

技術分享圖片

雙精度浮點數的指數偏移量是1023或十六進制的3FFh,因此該格式存儲的數可以表示為:

(-1)sx1.fx2e-1032.

上面提到的關於單精度浮點格式下的0,無窮大(小)和NaN的判斷規則同樣適用於雙精度浮點格式。

雙精度浮點格式下可以表示的最小正數或負數位:

1.0000000000000000000000000000000000000000000000000000x2-1022

後面有52個0,同樣,可以表示最大為

1.1111111111111111111111111111111111111111111111111111x21023

十進制表示的範圍是2.2250738585072014x10-308~1.17976931348623158x10308

雙精度浮點格式的有效數有53位(包括前面沒有列出的一位),大致相當於十進制的16位。與單精度浮點格式相比,這已經有了很大的改進,但仍然不能避免兩個不同的數存儲為同一個數的情況。例如:140737488355328.00和140737488355328.01。在內存中,兩書會被當做同一個數來處理,他們的雙精度浮點格式表示為:42E0000000000000h即1.0000000000000000000000000000000000000000000000000000x247

那麽浮點的運算該怎麽辦?前面我們講了正數的加減乘除運算了。

浮點數加法中,最重要的一點就是如何對有效數相加,為了能使它們的有效位匹配,需要利用指數來確定對其如何移位。假設要進行下面的加法運算:

(1.1101x25)+(1.0010x22)

你需要把有效數部分的11101和10010相加,但並不是簡單的相加。兩個數的指數部分的不同決定了第二個數必須相對於第一個數右移。實際上我們要做的整數加法應該是11101000加10010.最後的運算結果是:1.1111010x25

兩個浮點數的乘法意味著要把有效數當做整數相乘,並且把指數部分相加。為了使結果規範化,一般需要對指數調整一次到兩次。

浮點數運算的另一層次的復雜性體現在處理一些較為繁雜的函數運算,例如平方根、指數、對數和三角函數。但所有的都可以通過加減乘除來實現。

IBM在1954年發布了IBM704,它是第一臺將浮點數運算硬件作為可選配件的商用計算機,該機器以36位來存儲所有的數。對於浮點數,36位被分為27位的有效數,8位的指數和1位的符號位。浮點運算硬件可以直接進行加法減法乘法除法運算,其他的浮點運算則必須通過軟件來實現。

1980年開始,浮點運算硬件開始應用於桌面計算機,這起始於英特爾當年發布的8087數字協同處理芯片,當時這種集成電路被稱做數學協同處理器或浮點運算單元。8087不能獨立工作,它只能與8086或8088芯片一起工作,因此被稱為協處理器。

8087擁有40個管腳,它使用的很多信號與8086或8088完全相同。微處理器和數學協處理器通過這些信號相連。當CPU讀取到一條特殊指令ESC時——協同處理其開始接管控制權並執行下一條機器指令,該指令可以使三角函數、指數和對數等68條指令中的任一條。它所處理的數據類型遵循IEEE標準。在當時,8087被認為是市面上最高水平的集成電路。

可以把協處理器當做一個小型的自包含計算機。當響應某個特定的浮點運算機器碼指令時,協處理器會以固有的方式執行存放在ROM中屬於自己的指令序列。這些內部指令稱做微代碼。通常,這些指令都是循環的,因此不能立即得到最終結果。雖然如此,但數學協處理器在運算速度方面仍然表現優異,與軟件方法相比,其速度至少是後者的10倍。

在1990年發布的68040芯片中,摩托羅拉首次將FPU集成在了CPU中。

11、定點數和浮點數