電腦底層到底是如何存儲數字的?
- 2019 年 10 月 12 日
- 筆記
電腦對外資訊展示方式有文字、圖片、音頻、影片等,但不論應用在什麼地方,資訊在機器內部的形式都是一致的,即均為0和1組成的各種編碼。
一、有符號數和無符號數
在電腦中參與運算的數有兩大類:無符號數和有符號數。
無符號數
電腦中的數均放在暫存器中,通常稱暫存器的位數為機器字長。
所謂無符號數,即沒有符號的數,在暫存器中的每一位均可用來存放數值。當存放有符號數時,則需留出位置存放符號。
因此,在機器字長相同時,無符號數與有符號數所對應的數值範圍是不同的。
以機器字長為16位為例,無符號數的表示範圍為 0~65535,而有符號數的表示範圍為 -32768 ~ +32767(此數值對應補碼錶示)。
有符號數
對有符號數而言,符號的「正」、「負」機器是無法識別的,但由於「正」、「負」恰好是兩種截然不同的狀態,如果用「0「表示「正」,用「1」表示「負」,這樣符號也被數字化了,並且規定將它放在有效數字的前面,即組成了有符號數。
例如,+1100 在機器中表示為 01100 ,-1100 在機器中表示為 1 1100 。
在Java語言中,如 int、float 等都是有符號數,故下文所講都是在有符號數的範疇。
二、機器數與真值
把符號(如+、-)「數字化」的數稱為機器數,而把帶「+」或「-」符號的數稱為真值。
一旦符號數字化後,符號和數值就形成了一種新的編碼。在運算過程中,符號位能否和數值部分一起參加運算?如果參加運算,符號位又需作哪些處理?這些問題都與符號位和數值位所構成的編碼有關,這些編碼就是原碼、補碼、反碼和移碼。
原碼
原碼是機器數中最簡單的一種表示形式,符號位為0的表示正數,符號位為1的表示負數,數值位即真值的絕對值,故原碼錶示又稱為帶符號的絕對值表示。
反碼
正數的反碼依舊等於原碼,負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反。
補碼
正數的補碼碼依舊等於原碼,負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1。 (即在反碼的基礎上+1)
移碼
同一個真值的移碼和補碼僅差一個符號位,若將補碼的符號位由「0」改為「1」,或從「1」改為「0」,即可得該真值的移碼。簡單說,無論正負數,只要將其補碼的符號位取反即可。
三、定點數與浮點數
在電腦中,小數點不用專門的器件表示,而是按約定的方式標出,共有兩種方法表示小數點的存在,即定點表示和浮點表示。定點表示的數稱為定點數(如 java 語言中的 int),浮點表示的數稱為浮點數(如 java 語言中的 float、double)。
定點數
小數點固定在某一位置的數為定點數,有以下兩種格式。
當小數點位於數符和第一數值位之間時,機器內的數為純小數;當小數點位於數值位之後時,機器內的數為純整數。
採用定點數的機器稱為定點機。數值部分的位數n決定了定點機中數的表示範圍。若機器數採用原碼,小數定點機中數的表示範圍是 -(1 – 2^-n) ~ (1 – 2^-n),整數定點機中數的表示範圍是 -(2^n-1) ~ (2^n-1)。
浮點數
實際上電腦中處理的數不一定是純小數或純整數(如圓周率3.1416),而且有些數據的數值範圍相差很大(如電子的品質9×10-6g,太陽的品質2×103g),它們都不能直接用定點小數或定點整數表示,但均可用浮點數表示。浮點數即小數點的位置可以浮動的數,如
352.47 = 3.5247 * 10^2 = 3524.7 * 10^-1
顯然,這裡小數點的位置是變化的,但因為分別乘上了不同的 10 的方冪,故值不變。
通常,浮點數被表示成 N = S * r^j , 式中,S為尾數(可正可負),j為階碼(可正可負),r是基數(或基值)。在電腦中,基數可取2,4、8或16等。
浮點數的規格化形式為 N = 0.110101 * 2^10。
浮點數在機器中的形式如下所示。
浮點數由階碼j和尾數S兩部分組成。階符表示階碼數值部分的正負,數符表示尾數數值部分的正負。階碼j反映了浮點數的表示範圍及小數點的實際位置。尾數是小數,其位數n反映了浮點數的精度。
定點數與浮點數的比較
定點數和浮點數可從如下幾個方面進行比較。
①當浮點機和定點機中數的位數相同時,浮點數的表示範圍比定點數的大得多。
②當浮點數為規格化數時,其相對精度遠比定點數高。
③浮點數運算要分階碼部分和尾數部分,而且運算結果都要求規格化,故浮點運算步驟比定點運算步驟多,運算速度比定點運算的低,運算線路比定點運算的複雜。
④在溢出的判斷方法上,浮點數是對規格化數的階碼進行判斷,而定點數是對數值本身進行判斷。例如小數定點機中的數其絕對值必須小於1,否則「溢出」,此時要求機器停止運算,進行處理。為了防止溢出,上機前必須選擇比例因子,這個工作比較麻煩給編程帶來不便。而浮點數的表示範圍遠比定點數大,僅當「上溢」時機器才停止運算,故一般不必考慮比例因子的選擇。
總之,浮點數在數的表示範圍、數的精度、溢出處理和程式編程方面(不取比例因子)均優於定點數。但在運算規則、運算速度及硬體成本方面又不如定點數。因此,究竟選用定點數還是浮點數,應根據具體應用綜合考慮。一般來說,通用的大型電腦大多採用浮點數,或同時採用定、浮點數;小型、微型及某些專用機、控制機則大多採用定點數。當需要作浮點運算時,可通過軟體實現,也可外加浮點擴展硬體(如協處理器)來實現。
四、IEEE 754標準
現代電腦中,浮點數一般採用 IEEE 制定的國際標準,這種標準形式如下:
按 IEEE 標準,常用的浮點數有三種:
符號位S | 階碼 | 尾數 | 總位數 | |
---|---|---|---|---|
短實數 | 1 | 8 | 23 | 32 |
長實數 | 1 | 11 | 52 | 64 |
臨時實數 | 1 | 15 | 64 | 80 |
其中,S為數符,表示浮點數的正負,但與其有效位(尾數)是分開的。
階碼用移碼錶示,階碼的真值都被加上一個常數(偏移量),如短實數、長實數和臨時實數的偏移量用十六進位數表示分別為 7FH、3FFH 和 3FFFH。
尾數部分通常都是規格化表示,即非「0」的有效位最高位總是「1」。
下面列出了十進位數 178.125 的實數表示。
實數表示 | 數值 | ||
---|---|---|---|
原始十進位數 | 178.125 | ||
二進位數 | 10110010.001 | ||
二進位浮點表示 | 1.0110010001*2^111 | ||
符號 | 偏移的階碼 | 有效值 | |
短實數表示 | 0 | 0000 0111+0111 1111 =1000 0110 |
0110 0100 0100 0000 0000 000 |
你也可以編寫 java 程式來驗證在機器上浮點數是否是以 IEEE754 標準存儲的,示例程式碼如下:
@Test public void test(){ int i = Float.floatToIntBits(178.125f); System.out.println(Integer.toBinaryString(i)); //0 10000110 01100100010000000000000 }