第3章信息的表示
在表示數據或者與計算機通信時,用戶要依靠符號——數字、字母和標點符號,它們一起構成了字符串(CharacterString)。
例如,下面的代碼行:
1i=15;r=1.5;
2car1="15";car2="Hello";
3DIR>Result.doc
4catResult.tex
被解釋為程序的指令(第1、2行)或者發送給操作系統的命令(第3、4行)。這種數據的外部表示(ExternalRepresentation)不能直接被機器所理解。它需要翻譯(編碼(Code))成計算機可以使用的格式。我們將這種操作的結果稱為內部表示(InternalRepresentation)。它涉及使用通過0和1表示的邏輯符號的各種情況(參見3.2.2節)。出于清晰和/或簡化規范的原因,通常把邏輯(Logical)數據劃分成8個元素的組,稱為字節(Byte)。
在本章中,將區分以下類型:數字、整數或實數和字符。
再次考慮前面的示例:依賴于數據是存儲在變量i還是變量car1中,數據“15”的內部編碼將是不同的。一種是數值(Numerical),另一種是字符串(CharacterString)。對于兩個實體來說,其外部表示是相同的,盡管事實上它們本質上根本不同。人類操作員能夠區分它們,并且可以根據環境或者使用他們所了解的關于對象的知識來采納他們的處理方式。另一方面,對于不同類型的對象,機器需要不同的內部表示。在本章中,將介紹使得有可能把外部格式(ExternalFormat)轉換成內部格式(InternalFormat)的規則,而無須假定結果在機器的存儲器中最終是如何植入的。
3.1復??習
3.1.1以2為基數
以b為基數的數字x的表示(Representation)被定義為矢量{an,…,a0,a–1,…,a–p},滿足:
其中,ai是0~b–1之間的整數。索引i和數bi分別是符號ai的位置(Position)和加權(Weight)。系數an和a?p分別是最高有效位(MostSignificantDigit)和最低有效位(LeastSignificantDigit)。對于基數2(二進制編碼(BinaryCoding))來說,系數ai可能假定為值0或1,并將被稱為位(Bit),它是二進制數位(BinaryDigit)的簡寫形式。
示例3.1:
二進制數1010=1×23+0×22+1×21+0=1010。
從十進制轉換成二進制的整數部分是通過2的除法系列(SeriesOfDivisions)完成的,而小數部分則是通過2的乘法系列(SeriesOfMultiplications)完成的。考慮十進制數20.375。
可以通過執行以下操作將其轉換為二進制表示。
(1)對于整數部分xINT,執行除法系列:
202
0102
052
122
01
結果是通過最后的商和前面的余數給出的,得到xINT=101002。
(2)小數部分xFRAC是通過2的乘法系列獲得的,因此,對于0.375:
0.375×2=0.75
??????????????0.75×2=1.5
??????????????0.5×2=1
小數部分的數字是通過乘以2的結果的整數部分給出的。這里,得到xFRAC=0.0112。最后,20.37510=xINT+xFRAC=10100.0112。注意:二進制表示不一定是有限的,即使十進制表示是這樣的。因此,0.210將變成0.001100110011…。小數部分的位數是無限的。
通過限制表示的位數而引入的誤差稱為截斷誤差(TruncationError)。在這種表示中被舍入的誤差稱為化整誤差(RoundingError)。
例如,通過截斷,得到0.210≈0.0011001100;通過化整,得到0.210≈0.0011001101。
3.1.2二進制、八進制和十六進制表示
在我們特別感興趣的二進制中,無論數據是否是數字,用于數據表示的兩種邏輯狀態使用符號0和1表現。出于實際的原因,外部表示通常使用基數8(八進制(Octal)Representation)或基數16(十六進制(Hexadecimal)Representation)。
八進制系統使用8個符號:0、1、2、3、4、5、6和7。從基數2轉換為基數8(=23)是通過“從小數點開始”,將二進制數位三位一組地進行劃分即時完成的。例如:
1011101.011012=1|011|101.011|010=135.328
基數16使用符號0、1、2、3、4、5、6、7、8、9、A、B、C、D、E和F。從基數2轉換為基數16(=24)是以相同的方式完成的,即“從小數點開始”,將二進制數位4位一組地進行劃分。例如:
1011101.011012=101|1101.0110|10=5D.6816
這些基數不僅提供了二進制數位的精簡表示,而且使得有可能即時轉換成基數2。
3.2數字表示約定
數值的表示需要使用一些規則,它們有利于硬件和軟件處理。我們將不會提及所有現有的約定,因此這里將只討論最常見的約定。
3.2.1整數
1.經典表示:符號和絕對值
在第一種約定中,表示將使用符號位(0→+、1→?)以及用二進制編碼的數的絕對值。表3.1給出了利用這種約定的16位的表示。
表3.1符號和絕對值表示
十進制值符號/絕對值十六進制表示
+20/0000000000000100002
+00/0000000000000000000
–01/0000000000000008000
–31/0000000000000118003
在這種表示中,有+0和?0。對于設計用于處理以這種方式編碼的數字上的操作的電路,將具有比那些用于處理以2的補碼(Two’sComplement)編碼的數字的電路更高的復雜性。
2.1的補碼表示
負數及其絕對值x是用n位編碼的,使得x+=2n–1(“逐位”求補)。注意:可以通過00…0和11…1表示“0”。
3.2的補碼表示
這種表示沒有上面提到的缺點。負數的2的補碼編碼是通過獲取其絕對值相對于2n的補碼完成的,其中,n是用于編碼的位數。數及其補碼的二進制求和的結果是n以及一個進位1。如果把定義為A的2的補碼,則有:
A+=2n
表3.2顯示了幾個十進制數及其使用16個二進制數位表示的二進制數之間的對應關系。
表3.22的補碼表示
十進制值二進制編碼十進制值二進制編碼
20000000000000010?11111111111111111
10000000000000001?21111111111111110
00000000000000000
從一個正數轉換成一個具有相同絕對值的負整數,或者執行相反的操作,是通過對數字逐位求補,然后把求補的結果加1完成的。
這是因為,根據定義:
=2n?A=(2n?1)??A+1
而((2n?1)??A)是通過對A逐位求補得到的。
示例3.2:要獲得整數?1010的16位的2的補碼表示,首先從1010的二進制表示開始,即00000000000010102,然后對其求補:
(216?1)??10==1111111111110101
然后將其加1,得到:
11111111111101102,即FFF616或1777668
常見的編程語言使用16、32或64位的2的補碼表示整數。可以輕松確認:在16位的表示中,任何整數N都滿足:
?3276810≤N≤3276710
4.二進制編碼的十進制
在某些情況下,我們不使用二進制表示,而更喜歡使用另外某種編碼方式,它使得更容易從十進制編碼轉換成機器表示。常用的代碼稱為二進制編碼的十進制(Binary-Coded-Decimal,BCD)。
對于以十進制表示的數的每個數位,都使用4位進行編碼。這種表示或者其他共享相同概念的表示通常使用在用于管理的語言(如COBOL)中。盡管BCD編碼在操作期間的內部過程比使用2的補碼約定的數字更復雜(由于硬件計算單元通常操作的是2的補碼表示),但它在管理中展示了一個重要的優點:當從十進制轉換成內部表示時,將不會有截斷誤差(TruncationError)(參見3.2.2節)。
符號是單獨編碼的,將給其分配一個半字節,它所具有的值不同于用于數位的代碼。
有幾種BCD代碼:BCD-8421或BCD、Excess-3BCD(XS-3,0被編碼為0011,1被編碼為0100等)以及BCD-2421(0~4的編碼方式與BCD中相同,5~9則是從1011~1111編碼的)。最后兩個代碼是對稱的,“逐位”求補則導致了對應十進制表示的9的補碼。在BCD“Comp-3”表示中(IBM的打包十進制(PackedDecimal)表示),+符號被編碼為C(1100),–符號則被編碼為D(1101)。
示例3.3:整數–1289被表示為:
3.2.2實數
有兩種表示實數的方法:定點(Fixed-Point)表示和浮點(Floating-Point)表示。
1.定點表示
定點表示通常用在機器只用于處理整數以及計算速度至關重要的領域(例如,在信號處理中)。即使有誘惑力,但是其中包含以“科學”或“浮點”格式編碼數字的解決方案將導致處理時間和能耗顯著增加。
“定點”表示將小數點任意放置在二進制表示的兩個數位之間。其中的k位被分配給小數部分的表示被稱為Qk表示法。顯然,必須先分析使用的值的動態性,以避免可能被處理導致的任何飽和度。
示例3.4:可以使用以下方式在Q8中以N=16位編碼數5.75:
00000101.11000000
其中,點是象征性地表示的,以指示編碼。
對應的整數是通過對實數乘以2k的結果進行四舍五入獲得的。利用這種約定(k=8),數?5.75將編碼為:
?5.75×28=?147210=FA4016=11111010.01000000
從操作的角度講,兩個Qk數的和是Qk,而它們的乘積是Q2k。另請注意,重要的數字會出現在結果的最高有效位一端,而不會出現在最低有效位一端!這解釋了在某些處理器中存在乘法移位(Multiplication-Shift)運算符,在執行乘法運算后具有一個Qk。
示例3.5:考慮Q3定點中以4位編碼的數。我們將執行“帶符號”的乘法。獲取結果需要右移三位。有三種可能的情況,現在將介紹它們。
(1)首先,設兩個數均為正:
(2)利用相同的編碼規則,現在考慮兩個具有相反符號的數:
(3)利用相同的編碼規則,對于兩個負數:
在實際中,使用的主要格式是Q15,它需要對處理的數進行移位,使得它們的模數小于0.5。
在這類編碼中,管理小數點的位置就作為一項任務留給程序員完成,他們必須增加表示的位數,以維持相同的精度。要執行P個加法,必須向表示中添加log?2P個位。乘法提出了一個更困難的挑戰。以N位編碼的兩個數的乘積的結果將通過2N位表示。執行一系列的截斷可能導致災難性的結果。
2.浮點表示
在幾種常見的高級編程語言中,當以下面任何一種格式聲明變量x時,就使用這種表示。
floatx;inCorJava
singlex;inBasic
x;Float;inAda