2017-02-09 68 views
1

我有一個位操作方法,它將一個數乘以五分之八,如果有一個餘數向0舍入,該方法有效,我幾乎理解了所有的。然而,當我審查它時,我意識到我不確定如何解釋舍入誤差,其中它會繞着更負的數字而不是0,並且我需要理解爲什麼該線路起作用。據我所知,將multiplyByFive 31位向右移只會檢查變量的符號,如果是負值,則產生所有的符號,所以如果使用7,將會產生所有的零,如果是正數,或者y是二元的,如果是負數。如果我的理解是正確的,那麼爲什麼要加上乘以五個八分之一併將總和除以8得到一個負數就沒有錯誤。位操作 - 理解舍入零偏置乘以負數的分數

int multFiveEights(int x) { 

分解成由5相乘,然後通過8 除以變速它兩到左邊由四個相乘,加上X使得它由5

int multiplyByFive = (x << 2) + x; 

如果結果是否定的,和2^31 = 7之前右移

int addNumber = 7 & (multiplyByFive >> 31); 

11111111(如果按31右移時,負你全1)

將返回若爲陽性,1例全0的LSB,如果負

增加7 multiplyByFive佔錯誤

如果其負面它會嘗試向下舍朝向更負號去,所以取與它7分佔該錯誤/測試爲一個剩餘

int fiveEigths = (multiplyByFive + addNumber) >> 3; 
return fiveEigths; 
+0

如果'x'是肯定的,那麼你明白爲什麼'X/8'幾輪下來,但'(X + 7)/ 8'四捨五入? – immibis

回答

1

addNumber將在multiplyByFive爲負值時爲7,當值爲正值時爲0(我假設您瞭解這部分內容)。

因此,邏輯是在向右移3之前將7添加到multiplyByFive,但只有當它爲負時。

要理解爲什麼這會起作用,請考慮舍入和舍入之間的差異,以較低的3位表示。

當低3位爲零時,四捨五入和四捨五入不會產生任何差異,因爲不需要發生舍入,因爲數字是8的倍數,因此除以8(這就是正確的移位3)產生一個整數結果。

當低3位是其他任何東西時,則最終結果捨去的次數將少於四捨五入的結果。

通過添加7,就會增加1的最終結果,通過時鐘在每種情況下的第4位除了當低3位是零。如果他們都爲0,增加7將下3位設置爲1,但不會影響到4日,離開移位後的結果不變。

1

(multiplyByFive + 0) >> 3除以8(總是向下舍入),以及由8
(multiplyByFive + 7) >> 3劃分(總是向上舍入)。

您的代碼總是通過檢查零所在的方向朝向零進行舍入,然後在該方向舍入。如果要分割的數字是負數,則它增加7,所以它向上舍入(即趨向零)。如果它是正數,那麼它加0,所以它減少(也趨向於零)。