Matlab 教材:利用 Matlab 認識 IEEE 浮點數標準

事實上,Matlab 的標準內建資料型態只有一種:雙精度浮點數。 Matlab 很聰明地利用雙精度浮點數的底數部份來處理整數, 而雙精度浮點數的底數共有 53 位元 (其中第一位必定是 1), 所以它可以用無號整數規格表達的最大整數是 (53 個 1)

11111111111111111111111111111111111111111111111111111
等於十進制的 253-1。 但是 253 恰好是可以正確用浮點數表達的整數: 底數為 1 而指數為 (十進制的) 53。 比 253 更大的整數, 就不一定能夠正確地使用 64 位元之雙精度浮點數來表達了。

除非經過特殊處理,Matlab 的數值都屬於雙精度浮點數型態。 Matlab 顯示數值的正常格式,是所謂的 short 格式:

例如說
pi
得到 3.1416,說
10*pi
得到 31.4159,說
100*pi
得到 314.1593,但是說
1000*pi
就得到了 3.1416e+03。

其實一個雙精度浮點數大約有十六位十進制的數字。 Matlab 的 long 輸出規格,可以顯示所有的十進制數字。下指令

format long
將輸出格式定為 long。Matlab 也會考慮數值的「大小」而自動採取定點或科學記號。 例如說
pi
得到 3.14159265358979,而
1000*pi
會得到 3.141592653589793e+03。

用指令

format short
恢復普通的數值輸出格式。

Matlab 還有一個特殊的輸出格式:hex,把數值的雙精度浮點數之位元排列, 用 16 個十六進制數字展示出來。 因為雙精度浮點數共有 64 位元,每四個位元對應一個十六進制的數字, 因此一個雙精度浮點數的位元排列可以用 16 個十六進制數字展示出來。 例如先下指令改變輸出格式

format hex
然後輸入一個常數就看到這個數的位元排列。例如
1
得到答案
3ff0000000000000
這顯然不是 1 的無號整數或有號整數之位元排列,它是 1.0 的雙精度浮點數位元排列。

如果十六進制看不清楚,可以轉換成二進制字串來觀察。 但是以下指令其實無效:

dec2bin(hex2dec('3ff0000000000000'), 64)
因為 3ff0000000000000 的數值已經超過 253, Matlab 的 hex2dec() 函式不一定能正確處理這麼大的整數。 讀者不妨試試看
dec2bin(hex2dec('3ff000000000000F'), 64)
得到答案
0011111111110000000000000000000000000000000000000000000000000000
顯然是錯的:最後四嗶應該是 1 才對。

因此,我們只好自力救濟:自己寫一個十六進制轉換到二進制數字的函式。 以下是 hex2bin() 的原始碼,放在 hex2bin.m 檔案內。 注意這個檔案裡面還寫了一個小函式 ishex() 幫忙檢查輸入的字元是否為合法的十六進制數目字。

function t = hex2bin(s, n)
% Given a string s of hexadecimal numerals (0 1 2 3 4 5 6 7 8 9 A B C D E F),
% hex2bin(s) returns an equivalent string of binary numerals (0 1).
% The second argument n, which is optional, forces at least n digits to be
% presented on the output.
%
% Shann, 2004-05-12
 
if (~ischar(s))
    disp('Please input a string of hexadecimal numerals');
    return;
end
 
s = upper(s);
t = [];
for k=length(s):-1:1
    if (ishex(s(k)))
        t = [dec2bin(hex2dec(s(k)),4) t];
    else 
        clear t;
        disp('Please input a string of hexadecimal numerals');
        return; 
    end
end     
            
% Clean up the leading 0s
k = 1;      
while (t(k)=='0')
    k = k+1;
end     
t = t(k:end); 
         
% Check for the second argument
if ( nargin==2 & n>length(t) )
    for k=1:(n-length(t))
        t = ['0' t];
    end
end
 
function ans = ishex(c)
% Input a character c, check if it is a hexadecimal digit.  That is,
% 0 1 2 3 4 5 6 7 8 9 A B C D E F
% We assume the input characters are in upper case.
 
if ((c>='0' & c<='9') | (c>='A' & c<='F'))
    ans = 1;
else
    ans = 0;
end
將上述 M-file 安裝好之後,實驗
hex2bin('3ff000000000000F',64)
得到正確答案
0011111111110000000000000000000000000000000000000000000000001111

現在我們可以做實驗了。下指令

format hex
5.78125
format long
得到 5.78125 的雙精度浮點數位元排列 4017200000000000,轉成二進制數字
hex2bin('4017200000000000', 64)
得到
0100000000010111001000000000000000000000000000000000000000000000
其中 因此,上述位元排列代表了二進制的科學記號
+1.0111001 * 22
也就是二進制的小數 101.11001,轉換成十進制數字應該是
22 + 1 + 2-1 + 2-2 + 2-5 = 5 + 1/2 + 1/4 + 1/32 = 5.78125

習題

  1. 請描述雙精度浮點數 Inf 的位元排列特徵。
  2. 請描述雙精度浮點數 NaN 的位元排列特徵。
  3. 請描述 1.0 的雙精度浮點數位元排列。
  4. 請描述 2.0 的雙精度浮點數位元排列。
  5. 請描述 1/3 的雙精度浮點數位元排列。
  6. 請描述 2-1070 的雙精度浮點數位元排列。
單維彰 (2004/05/12) --- [Prev] [Next] [Up]