1. 程式人生 > >《深入理解計算機系統》 練習題2.42-2.44

《深入理解計算機系統》 練習題2.42-2.44

補碼除以2的冪

具體講解在書裡。這裡直接給幾個結論:
1)有符號數即補碼數執行的是,算術右移。

2)有變數x和 2 k 2^k (0<=k<w),那麼 x &gt;

&gt; k x &gt;&gt;k 將產生數值 x / 2
k \lfloor {x/2^k} \rfloor

3)正常來說,除法是向零取整,而不是固定的向下取整。所以為了負數除法有正確的結果,在移位前加偏置。所以,當x為負數時,將執行 ( x

+ ( 1 &lt; &lt; k ) 1 ) &gt; &gt; k (x + (1&lt;&lt;k)-1) &gt;&gt;k 產生數值 x / 2 k \lceil {x/2^k} \rceil
2 k 2^k 當做y,所以就是 x / y \lceil x/y \rceil = ( x + y 1 ) / y \lfloor (x+y-1)/y \rfloor

關於第3條結論,除了書中給出的證明,這裡給出一個直觀上的解釋:
( x + y 1 ) / y = x y + y 1 y (x+y-1)/y =\frac{x}{y} + \frac{y-1}{y}
假如 x y \frac{x}{y} 現在是一個負的小數,y為4, x y \frac{x}{y} 且可以分解為-3和 1 4 \frac{1}{4} ,本來-2.75向下取整是-3,就不是向零取整了。但這裡再加上一個 3 4 \frac{3}{4} ,結果就會變成-2,再向下取整,也是正確的結果-2了。
而且上面的分解過程, 4 \frac{?}{4} 是大於等於 1 4 \frac{1}{4} ,小於等於 4 1 4 \frac{4-1}{4} ,所以肯定能保證正確結果。

2.42原理

當x為非負數時,不加偏置。因為此時的向下取整就是向零取整。
當x為負數時,加偏置。

具體來說,就是得到x的符號位上的值是0還是1,如果是1,那麼就要加上偏置 2 4 1 2^{4}-1 即15。

2.42程式碼

int book_div16(int x)
{
        /* Compute bias to be either 0 (x >= 0) or 15 (x < 0) */
        int bias = (x >> 31) & 0xF;//右移31位後,32位上面都是符號位的值
        //如果為非負數,符號位為0,bias變數為0
        //如果為負數,符號位為1,bias變數為0xF,即15
        return (x + bias) >> 4;
}

如上為原書實現。

2.43

在這裡插入圖片描述
先看M:
程式碼等價於x = x * 32 -x = x * 31.所以M為31.
再看N:
7 = 2 3 2^3 -1,最後的右移操作也是右移3位,所以N為 2 3 2^3 即8.

2.44

int x = foo();
int y = bar();
unsigned ux = x;
unsigned uy = y;
對於以下的各表示式,回答兩個問題:(1)對於任意的x和y值,該表示式是否為true,
(2) 當x和y取什麼值時為false

A. (x > 0) || (x-1 < 0)
當x為TMIN時,左邊不符合條件,為0;右邊負溢位為TMAX,正數不小於0,為0;此時為false

B. (x & 7) != 7 || (x<<29 < 0)
左邊要求的是x的低3位不能都為1;右邊要求第3位為1(先左移29位,所以有原始的低3位和29位個0組成,此時小於0,說明符號位為1,即原始的低3位的最高那個為1);
低3位分兩種情況:
1)除111外的所有情況:左邊符合,必返回1,不用管右邊。
2)111:左邊不符合,但右邊符合了,也返回1。
該表示式必為true。

C. (x * x) >= 0
很明顯會出現正溢位,但這裡和加法的溢位不一樣,加法正溢位最多能獲得第w+1位的權值 2 w 2^w ,且正溢位結果必為負數。
但這裡就不一樣了,因為乘積的結果可能很大。正溢位的結果也是可能正,可能負。
規律如下:
將乘積設為s,如果s- 2 w 2^w 為負數,那麼s- 2 w 2^w 則為溢位結果。
如果s- 2 w 2^w 為非負數,那麼(s- 2 w 2^w )% 2 w 2^w 則為溢位結果。

	short a, b, c;
	a = b = 182;
	c = a * b;

在這裡插入圖片描述
182*182-65536=33124-65536=-32412

	short a, b, c;
	a = b = 270;
	c = a * b;

在這裡插入圖片描述
(270*270-65536)%65536=(72900-65536)%65536=7364%65536=7364

	short a, b, c;
	a = b = 400;
	c = a * b;

在這裡插入圖片描述
(400*400-65536)%65536=(160000-65536)%65536=94464%65536=28928
非要說原因的話,就是加法正溢位會導致第w位的權值為1,而乘積正溢位就不一定了。

D. x<0 || -x <= 0
當x為0時,右邊成立;
當x為[1,TMAX],右邊必成立;
當x為[TMIN+1,-1],左邊成立;
當x為TMIN,左右都成立;
綜上,此表示式必為1.

E. x>0 || -x >= 0
當x為0時,右邊成立;
當x為[1,TMAX],左邊成立;
當x為[TMIN+1,-1],右邊成立;
當x為TMIN,左右都不成立;

F. x+y == uy+ux
表示式中含有無符號數,所以左邊也會轉換為無符號數。等價於unsigned(x+y) == uy+ux.
在二進位制上,無符號數和有符號數的加法是一樣的,故都為真。
例如:x=y=-1,則ux=uy= 2 32 1 2^{32}-1 (TMAX).
x+y = -2 ,再轉無符號明顯是 2 32 2 2^{32}-2 (TMAX-1,除最低一位為0外,其餘都為1)
x+y = ( 2 32 1 2^{32}-1 )*2 - 2 32 2^{32} = 2 33 2^{33} - 2 - 2 32 2^{32} = 2 32 2 2^{32}-2 .

G. x*~y + uyux == -x
-y = ~y+1,故 ~y=-y-1, 左邊= x
(-y-1)+uyux = uyux - xy -x, 不管是無符號數還是有符號數,在二進位制層面上相乘後截短後的結果都是相同的。故 uyux-x*y=0, 故結果都為真,道理同上。

參考連結:
[1] https://github.com/haiiiiiyun/book_exercises/blob/master/csapp-v3/chap2/2.43-2.54.txt#L10