本章主要研究三種重要的數字表示,分別是無符號編碼、補碼編碼和浮點數編碼。其中,無符號編碼表示大於或等於零的數字,補碼編碼用來表示有符號整數,浮點數編碼是科學計數法的以2爲基數的版本。linux
特殊的轉換方法數組
當值x是2的非負整數的n次冪時即 \[x=2^n\] 能夠將x寫成1後面加n個0的形式。
當n表示爲 n=i+4j 時(0<=i<=3),x對應的十六進制數字能夠寫成一、二、四、8後面跟J個0
例如: \[ 512 = 2^9 \] 知 n=1+2*4 故2048對應的16進制是 0x200函數
下面show_bytes
函數的做用是打印出每一個以十六進制表示的字節,其中輸入是一個字節序列的地址。學習
void show_bytes(byte_pointer start,size_t len) { size_t i; for(i=0;i<len;i++) { printf("%.2x",start[i]); } printf("\n"); } void show_int(int x) { show_bytes((byte_pointer)&x,sizeof(int)); }
實現的功能就是輸出int型每一個字節對應的十六進制表示。優化
布爾運算 邏輯運算 命題邏輯 ~ NOT ┐ & AND ∧ | OR ∨ ∧ 異或 ⊕
【注】注意區分C語言中的邏輯運算與位級運算編碼
C語言的邏輯運算是|| &&和!,分別對應命題邏輯中的OR、AND和NOT運算。邏輯運算認爲全部的非零值都爲真,參數零表示假,運算結果只由0和1。
邏輯運算中若是第一個參數求值就能肯定表達式的值,邏輯運算不會對第二個參數求值spa
幾乎全部的編譯器/機器組合都會對有符號數使用算數右移,而對於無符號數,右移必須是邏輯右移。操作系統
無符號數只能表示非負數,而補碼編碼可以表示負數、0和正數。指針
無符號數的編碼code
無符號數的定義
對於向量 \[ \vec{x} = [x_{w-1},x_{w-2},\cdots,x_0] \] 有
\[B2U_w (\vec{x}) = \sum_{i=0}^{w-1}x_i2^i\]
無符號數所能表示的值的範圍
[0 0 …… 0] 到 [1 1 …… 1]即
\[UMax_w = \sum_{i=0}^{w-1}2^i = 2^w-1\]
無符號編碼的惟一性
函數B2U是一個雙射,將每個長度爲w的位向量,映射爲0~2^w-1之間的惟一一個值,這種映射是一一對應的關係,便可以反向操做。
補碼編碼
最多見的有符號數的計算機表示方式就是補碼形式,這種形式下,將字的最高有效位解釋爲負權。
對於向量 \[ \vec{x} = [x_{w-1},x_{w-2},\cdots,x_0] \] 有
\[B2T_w (\vec{x}) = -x_{w-1}2^{w-1} + \sum_{i=0}^{w-1}x_i2^i\]
最高有效位稱爲符號位,符號位爲1時,表示值爲負數;符號值爲0時,值爲非負。
它能表示的最小值是[1 0 …… 0] 其整數值爲 \[TMin_w = -2^{w-1} \]
最大值爲[0 1 …… 1] 其整數值爲\[TMax_w = \sum_{i=0}^{w-1}2^i = 2^w-1\]
強制類型轉換的結果保持位不變,只是改變了解釋這些位的方式。處理一樣字長的有符號數和無符號數之間的轉換通常規則是:數值可能會改變,可是位模式不變
補碼轉換爲無符號數
對知足\[TMin_w\leq x \leq TMax_w \]的x有:
\[T2U_w(x) =\begin{cases} x+2^w & x <0 \\\ x & x \geq 0 \end{cases}\]
從以上表達式能夠看出,將一個有符號數轉爲它相應的無符號數時,負數就被轉換成了大的整數,非負數則會保持不變。
對知足\[0 \leq u \leq UMax_w \]的x有:
\[U2T_w(u) =\begin{cases} u & x \leq TMax_w \\\ u-2^w & u>TMax_w \end{cases}\]
從以上表達式能夠看出,講一個無符號數轉換爲補碼時,U2T把大於2^w-1的數轉化成了負數。
從上述兩個公式能夠看出,對於在範圍\[ 0 \leq x \leq TMax_w \]的範圍內的數字有着相同的補碼和無符號數表示。對於這個範圍之外的數須要加上或者減去2^w
令\[\vec{x} = [x_{w-1},x_{w-2},\cdots,x_0]\] 現截斷該位向量k位的結果是\[x' = x mod 2^k\]
當x+y的結果s小於x或者小於y的時候,能夠斷定無符號數的加法出現了溢出。
模數加法造成了一個阿貝爾羣,對於每一個x值一定有有一個加法逆元。
對於知足\[ 0 \leq x <2^w \]的任意x值,其無符號加法逆元爲
\[- x =\begin{cases} x & x=0 \\\ 2^w-x & x>0 \end{cases}\]
補碼加法
對於知足\[-2^{w-1} \leq x,y \leq 2^{w-1}-1 \]的整數x和y 有
\[x + y =\begin{cases} x+y-2^w & 2^{w-1} \leq x+y & 正溢出 \\\ x+y & -2^{w-1} \leq x+y <2^{w-1} &正常\\\ x+y+2^w & x+y<-2^{w-1} & 負溢出 \end{cases}\]
補碼的非
對於知足\[ TMin\_w \leq x <TMin\_w \]的任意x值,其補碼的非爲
\[- x =\begin{cases} TMin\_w & x=TMin\_w \\\ -x & x>TMin\_w \end{cases}\]
無符號和補碼乘法
將一個數截斷w就等價於計算該值的模2^w
對於無符號和補碼乘法來講,乘法運算的位級表示都是同樣的。
乘以常數
因爲在大多數機器上,整數乘法的指令須要10個或者更多的時鐘週期,其餘整數運算只須要1個時鐘週期。編譯器使用了優化,試着用位移和加法的運算組合代替乘以常數因子的乘法。
原理: 設x的位模式爲 \([x_{w-1},x_{w-2},\cdots,x_0]\)表示無符號整數,那麼對於任何$k \leq 0 $都認爲 \([x_{w-1},x_{w-2},\cdots,x_0,0,0,\cdots,0]\) 給出了 \(x*2^k\) 的w+k位的無符號表示,右邊增長了k個0。
能夠看出,左移一個數值至關於執行一個與2的冪相乘的無符號乘法
例如:一個程序包含表達式 x*14 利用 $14 =2^3+2^2+2^1 $ 能夠將該乘法重寫(x<<3)+(x<<2)+(x<<1),將一個乘法替換爲位移和兩個加法。
或者利用 $14 =2^4-2^1 $ 重寫成 (x<<4)-(x<<1)
二進制小數
表示方法:$ b_m b_{m-1} \cdots b_1 b_0.b_{-1} b_{-2} \cdots b_{-n} $
這個表達描述的定義以下:
\[b = \sum_{i=-n}^{m}2^i*d_i \]
【注】浮點運算只由有限的範圍和精度,而且不遵照結合律。
本章重點在於用數學公式準肯定義出計算機中使用的幾種數據類型,內容不少,須要好好總結和複習。經過直接操做數字級的位表示,獲得了幾種算數運算的方式。針對不一樣的機器,變量類型存儲的大小也不一樣、存儲方式不一樣,爲了能使編寫的程序在所有範圍內正確工做,能夠實現跨越不一樣的機器、操做系統和編譯器的組合,對於這種數學原理的學習是十分重要的。 第二章主要從信息存儲的方式、整數表的方法(無符號編碼、補碼編碼)以及相關操做、整數運算(無符號運算、補碼運算)、浮點數(兩種表示方式)等方面介紹了數據的存儲表示方式,進行計算的結果等內容。