打卡!!!每日一题
今天给大家带来一道位运算类型的题目
题目描述:
题目示例:
对于这种类型的题目,当题目要求不能使用乘法、除法时,那么则需要我们从移位、或、与、异或等位运算的角度来进行考虑,接下来我带着大家从这道题目入手,看看位运算到底是怎么应用的
这题是除法,所以先普及下除法术语:
商,公式是:(被除数-余数)÷除数=商,记作:被除数÷除数=商…余数,是一种数学术语。
在一个除法算式里,被除数、余数、除数和商的关系为:(被除数-余数)÷除数=商,记作:被除数÷除数=商…余数,
进而推导得出:商×除数+余数=被除数。
要求商,我们首先想到的是减法,能被减多少次,那么商就为多少,但是明显减法的效率太低,那么我们可以用位移法,因为计算机在做位移时效率特别高,向左移1相当于乘以2,向右位移1相当于除以2
我们可以把一个dividend(被除数)先除以2^n,n最初为31,不断减小n去试探,当某个n满足 d i v i d e n d / 2 n > = d i v i s o r dividend/2^n>=divisor dividend/2n>=divisor时,表示我们找到了一个足够大的数,这个数*divisor是不大于dividend的,所以我们就可以减去2^n个divisor,以此类推
这样说可能不是特别直观,举个例子:
100/3,首先用100/2^31,即100>>31,在计算机中这个结果为0,所以不符合,再接着继续找
100>>30=0,结果还是不大于或等于除数,…,直到100>>5=3,刚好大于等于我们的除数3,这时我们将$ 100-2^5*3=4 $,也就是减去了32个3,接下来我们再处理4,同样手法可以再减去一个3
所以一共是减去了33个3,所以商就是33
代码如下:(Java)
public int divide(int dividend, int divisor) {
if (dividend == 0) {
return 0;
}
if (dividend == Integer.MIN_VALUE && divisor == -1) {
return Integer.MAX_VALUE;
}
boolean negative;
negative = (dividend ^ divisor) < 0;//用异或来计算是否符号相异
long t = Math.abs((long) dividend);
long d = Math.abs((long) divisor);
int result = 0;
for (int i = 31; i >= 0; i--) {
if ((t >> i) >= d) {//找出足够大的数2^n*divisor
result += 1 << i;//将结果加上2^n
t -= d << i;//将被除数减去2^n*divisor
}
}
return negative ? -result : result;//符号相异取反
}