请问移位和乘法的具体区别!

解决方案 »

  1.   

    使用移位运算来避免乘法运算是一种常用技巧,不过乘数必须都是正整数,而且必须至少有一个是 2 的 n 次方,例如:2,4,8,16,32……移位运算的特点是速度快,而乘法运算速度较慢,把乘法运算转化为移位运算可以稍微提高程序运行效率。例如:        num *= 32;
            等同于
            num <<= 5; /* 2 的 5 次方等于 32 */如果乘数不是 2 的 n 次方,我们可以把乘数分解成几个 2 的 n 次方的和:
            num *= 20; 
            等于
            num *= (16 + 4);
            等于
            num = num * 16 + num * 4; 
            等于
            num = (num << 4) + (num << 2); 不过,现在的编译器很聪明,它们会代替我们做这种优化。也就是说,如果我们写的语句是:
            num *= 100;
    编译器会把这个语句优化为:
            num = (num << 6) + (num << 5) + (num << 2);不知道还有什么区别。
      

  2.   

    往左移一位就是乘2, 往右移一位就是除2,右移分有符号>>和无符号右移>>>
    无符号右移会在高位自动补0
      

  3.   

    现代处理器应该把这两种计算法优化得都差不多了,可以从多种途径测试一下,看汇编码或者测试:long starttime = System.currentTimeMillis();
    for(long i = 0; i < 1000000000; i++) {
        int x = 100 << 2;
    }
    long endtime = System.currentTimeMillis();
    System.out.println(endtime - starttime);

    long starttime = System.currentTimeMillis();
    for(long i = 0; i < 1000000000; i++) {
        int x = 100 * 2;
    }
    long endtime = System.currentTimeMillis();
    System.out.println(endtime - starttime);时间越长越精确,当然这不能100%证明,但至少有一点,两个整数的乘法可以转换为位移操作和加法的组合,而加法和位移操作速度是没有区别的
    int c = 0;
    int b = 7;
    int a = 5;
        
    while(b!=0) {
        if((b & 1) != 0) {
            c = c + a;
    a <<= 1;
    b >>= 1;
        }
    }
    System.out.println(c);
      

  4.   

    现代 CPU 都含有乘法、除法指令,因此做这些与做移位的效率是一样的,没区别。只是那种非常 SB 的面试喜欢出一些“如何更高效地计算 2 * 8”这种问题纯属有病,而且还病得不清!两个常量的运算竟然交给计算机去算!
      

  5.   

    如果真想了解位运算的话,可以看一下这本书: Henry S. Warren, Jr. 写的的 Hacker's Delight,中文版书名:《高效程序的奥秘》。http://www.hackersdelight.org  这本书是位运算的巅峰之作。