这里最后需要提一下的是,加法、减法和移位的速度并不会总快于乘法运算,因此是否要进行上面的优化就取决于二者的速度了。
无符号除法除法与乘法不同,它不满足加法的分配律,也就是设y = m + n , x/y != x/m + x/n。而且不幸的是,它有时候会比乘法运算更慢,但是我们只能针对除数可表示为2k的除法运算进行优化,转换为算数右移或者逻辑右移k位的运算(无符号数为逻辑右移,为正数时,逻辑右移与算术右移效果一样)。
由于是除法,因此我们会涉及到舍入的问题。这里定义└x/y┘的值为a\',x/y为a,则对于a\',它是唯一一个整数,满足 a\' =< a < a\'+1。
比如└2.1┘的值就为2,而对于└-2.1┘则为-3,如果本身就是整数,则等于自身。
书中给出了无符号数除以2k等价于右移k位(w > k >= 0)的证明,这一证明过程相对比较复杂一点,LZ这里给出一个相对简单的证明方式,不采用书上的证明。如果各位看LZ的证明看不懂的话,也可以参照一下书上的方式。
我们假设对于一个w位的无符号数来说,假设它的位表示为[xw-1....x0],则x = xw-12w-1 + .... + x020 。因此就有以下结果。
x/2k = xw-12w-1-k +... + xk20 + xk-12-1 +...+ x02-k = B2Uw-k([xw-1....xk]) + xk-12-1 +...+ x02-k
由于xk-12-1 +...+ x02-k <= 2-1 + .... 2-k = (1-(1/2)k) < 1 (这里是证明的关键一步,先假设所有位为1,则利用等比数列求和公式即可得到),因此有└xk-12-1 +...+ x02-k┘ = 0。
因此我们可以得到└x/2k┘ = └B2Uw-k([xw-1....xk])┘ + └xk-12-1 +...+ x02-k┘ = └B2Uw-k([xw-1....xk])┘ = B2Uw-k([xw-1....xk]) = x >> k。
更直观的,我们可以使用程序验证这一结果,看下面的Java代码。
public class Main { public static void main(String[] args) { int a = 17; int b = 8; int c = a/b; System.out.println("a:" + Integer.toBinaryString(a)); System.out.println("b:" + Integer.toBinaryString(b)); System.out.println("c:" + Integer.toBinaryString(c)); System.out.println("a >> 3:" + Integer.toBinaryString(a >> 3)); } }