只用位运算不用算术运算实现
題目
給定兩個32位整數a和b,可正、可負、可0.不能使用算術運算符,分別實現a和b的加減乘除。
要求
如果給定的a和b執行加減乘除的某些結果本來就會導致數據的溢出,那么你實現的函數不必對那些結果負責。
基本思路
加法運算
使用位運算實現加法運算主要分為兩個部分。先計算完全不考慮進位進行相加的結果,再計算只考慮進位的產生值。將兩個結果相加就是最終的結果。
例如:?
a: 001010101?
b: 000101111
首先不考慮進位進行相加,結果為001111010,該結果其實就是a ^ b。
再考慮進位的產生值,結果為000001010,該結果其實就是(a & b)<< 1。
將1、2產生的結果再相加,此時依然要考慮兩部分:不考慮進位和只考慮進位。
一直重復上述步驟,直到進位產生的值全部消失。
?
減法運算
實現a - b只要實現a + (-b)即可。所以只要將a和b的相反數調用add函數就行。根據二進制數在機器中表達的規則,得到一個數的相反數,就是這個數的二進制數表達取反加1(補碼)的結果
public int negNum(int n){return add(~n,1) }public int minus(int a,int b){return add(a,negNum(b)) }乘法運算
用位運算實現乘法運算。a × b的結果可以寫成 a?20?b0+a?21?b1+...a?2i?bi+...a?231?b31a?20?b0+a?21?b1+...a?2i?bi+...a?231?b31. 其中bibi為0或1表示整數b的二進制表達中第i位的值(從右往左數)。該過程有點類似于求整數的N次方問題。具體實現參照如下代碼
?
除法運算
用位運算實現除法運算其實就是乘法的逆運算。定義 res 表示除法的結果。首先將a向右移位31位,然后看能不能容下b,如果能,說明a/231a/231可以包含一個b,等價于a可以包含一個b?231b?231,令res的第31位為1,此時a的值應該為a?b?231a?b?231;如果不能容下b,令res的第31位為0,a的值不變;接下來將a向右移位30位是否能容下b……重復步驟直到a?b?2i=0a?b?2i=0。?
以上過程只適用于a和b都不是負數的情況下,當a或b為負數時,可以先將a和b轉成正數,計算完之后再判斷res的真實符號就行。?
除法實現到這一步已經可以解決絕大多數情況了。但是我們知道,32位最小整數的絕對值要比最大整數大,所以如果a或b等于最小值,是不能轉換成相對應的正數的。這時候需要分情況考慮:
如果a和b都為最小值,直接返回1
如果a不為最小值,而b為最小值,那么a/b = 0,直接返回0
如果a為最小值,而b不為最小值。這時我們對a無能為力,但是我們可以讓a增大一點點,計算出一個結果然后再修正一下就可以得到最終的結果。處理過程如下:
<1>計算(a+1)/b(a+1)/b,結果記為c?
<2>計算c?bc?b?
<3>計算(a?c?b)/b(a?c?b)/b,結果記為rest?
<4>計算c+rest
?
?
總結
以上是生活随笔為你收集整理的只用位运算不用算术运算实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 特征工程-统计数据特征
- 下一篇: 整数的二进制表达中有多少个1