《深入理解計算機系統》 練習題2.42-2.44
補碼除以2的冪
具體講解在書裡。這裡直接給幾個結論:
1)有符號數即補碼數執行的是,算術右移。
2)有變數x和 (0<=k<w),那麼 將產生數值 。
3)正常來說,除法是向零取整,而不是固定的向下取整。所以為了負數除法有正確的結果,在移位前加偏置。所以,當x為負數時,將執行
產生數值
。
將
當做y,所以就是
=
關於第3條結論,除了書中給出的證明,這裡給出一個直觀上的解釋:
假如
現在是一個負的小數,y為4,
且可以分解為-3和
,本來-2.75向下取整是-3,就不是向零取整了。但這裡再加上一個
,結果就會變成-2,再向下取整,也是正確的結果-2了。
而且上面的分解過程,
是大於等於
,小於等於
,所以肯定能保證正確結果。
2.42原理
當x為非負數時,不加偏置。因為此時的向下取整就是向零取整。
當x為負數時,加偏置。
具體來說,就是得到x的符號位上的值是0還是1,如果是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 =
-1,最後的右移操作也是右移3位,所以N為
即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位的權值
,且正溢位結果必為負數。
但這裡就不一樣了,因為乘積的結果可能很大。正溢位的結果也是可能正,可能負。
規律如下:
將乘積設為s,如果s-
為負數,那麼s-
則為溢位結果。
如果s-
為非負數,那麼(s-
)%
則為溢位結果。
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=
(TMAX).
x+y = -2 ,再轉無符號明顯是
(TMAX-1,除最低一位為0外,其餘都為1)
x+y = (
)*2 -
=
- 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