zoukankan      html  css  js  c++  java
  • 有趣的位运算-移位运算

    1左移、右移、无符号右移

    左移(<<):运算符左边的对象向左移动运算符右边指定的位数(在低位补0)

    右移(>>):运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制(如果值为正,则在高位补0,如果值为负,则在高位补1)

    无符号右移(>>>):运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制(无论值的正负,都在高位补0)

    注:x<<y 相当于 x*2;x>>y相当于x/2y
        从计算速度上讲,移位运算要比算术运算快。
        如果x是负数,那么x>>>3没有什么算术意义,只有逻辑意义。(计算机是补码的形式存储)

    与按位运算符一样,移位运算符可以用于byte、short、int、long等整数类型,和字符串类型char,但是不能用于浮点数类型float、double;当然,在Java5.0及以上版本中,移位运算符还可用于byte、short、int、long、char对应的包装器类。

    2有趣的问题

    对一个int型的数字a,a>>32 = a<<32 = a。

    例如,整数1(0000 0000 0000 0001),按照上述规则1<<32 = 0(0000 0000 0000 0000),左移低位补0。而实际结果却是1.

    Think in Java给出了解释:

    “对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。只有右侧的5个低位才会有用。这样可防止我们在一个int数里移动不切实际的位数。若对一个long值进行处理,最后得到的结果也是long。此时只会用到右侧的6个低位,防止移动超过long值里现成的位数。”

    说白了就是移多了没什么意义。这里5个低位[00000,11111]。所以以上几个类型只有在[0,31]范围位移才有效。那么若位移数大于31会怎么样呢?

    jdk是这么做的:采用模运算。所以1<<32  = 1<<(32%32)= 1<<0 = 1。

    3位移运算在hashMap源码中的经典应用

        static int hash(int h) {  
            h ^= (h >>> 20) ^ (h >>> 12);  
            return h ^ (h >>> 7) ^ (h >>> 4);  
        }  

    之前看源码的时候一直不明白为什么要这么做。下面大家看一个例子可能就猜出来了(结合hashMap设计原则)

    public class Test {
    
        public static void main(String[] args) {
            Integer number1 = 80000;
            printInfo(number1.hashCode());
            printInfo(hash(number1.hashCode()));
            
            Integer number2 = 1024;
            printInfo(number2.hashCode());
            printInfo(hash(number2.hashCode()));
        }
        
        
        //  输出一个int的二进制数
        private static void printInfo(int num){
            System.out.println(Integer.toBinaryString(num));
        }
        
        static int hash(int h) {  
            h ^= (h >>> 20) ^ (h >>> 12);  
            return h ^ (h >>> 7) ^ (h >>> 4);  
        }  
    
    }

    输出:

    10011100010000000
    10010100101101011
    10000000000
    10001001000

    hashMap采用数组和链表实现,设计当然希望这个HashMap里面的 元素位置尽量的分布均匀些,尽量使得每个位置上的元素数量只有一个,那么当我们用hash算法求得这个位置的时候,马上就可以知道对应位置的元素就是我们要的,而不用再去遍历链表,这样就大大优化了查询的效率。而原始数据经过hash方法后,1的分布更加均匀。有没有想到点什么?不得不佩服设计这段代码的大神~

  • 相关阅读:
    Python常用转换函数
    Python随机数
    sublime text的pylinter插件设置pylint_rc后提示错误
    使用Pydoc生成文档
    字符编码笔记:ASCII,Unicode和UTF-8
    Windows编程MessageBox函数
    魔方阵算法及C语言实现
    iOS通讯录整合,兼容iOS789写法,附demo
    谈谈iOS app的线上性能监测
    ReactiveCocoa代码实践之-更多思考
  • 原文地址:https://www.cnblogs.com/ouym/p/8808671.html
Copyright © 2011-2022 走看看