zoukankan      html  css  js  c++  java
  • 有趣的位运算-与或非

    1与运算(&)

    0 & a = 0
    
    1 & a = a

    a表示0或者1任意值。

    (1)与运算判断奇偶

    能被2整除的数是偶数(二进制的最后一位是0),结合与运算的性质不难得出:

    a & 1 = 0 偶数
    
    a & 1 =1 奇数

    (2)与运算+异或求平均值

    有int类型变量x、y,现需要求其平均值。

    首先要求x+y的和,再除以2,但是有可能x+y的结果会超过int的最大表示范围(这里强行加入位运算,x和y分别除2再相加也不会越界啦)

    (x&y)+((x^y)>>1)

    &运算:相当于十进制 相同位做加法的1/2

    0101 & 0011   结果:二进制0001             十进制 (2^0 +2^0)/2          这里的"^"代表次幂

    (3)HashMap源码中与运算的妙用

    对于任意给定的对象,只要它的 hashCode() 返回值相同,那么程序调用 hash(int h) 方法所计算得到的 hash 码值总是相同的。我们首先想到的就是把hash值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,“模”运算的消耗还是比较大的,在HashMap中是这样做的:

    static int indexFor(int h, int length) {  
        return h & (length-1);  
    } 

    HashMap的底层数组的长度总是 2 的 n 次方,这是HashMap在速度上的优化。为什么呢?

    举个例子,若hashMap数组长度是15(1111),那么位置计算是h&(15-1),14(1110)的最后一位是0所以h的最后一位与操作永远是0,这样的后果是0001,0011,0101,1001,1011,1101这些尾数为1的空间永远不会放置数据,造成极大的空间浪费。

    而当底层数组的长度总是 2 的 n 次方时,h & (length-1)等价与h% (length-1),但是效率比前者要高很多。

    2或运算(|)

    0 | a = a
    
    1 | a = 1

    a表示0或者1任意值。

    |运算:相当于十进制 相同位做加法的1/2与不同位做加法求和

    0101 | 0011   结果:二进制0111             十进制 (2^0 +2^0)/2 +(2^2 +2^1)

    3非运算(~)

    ~运算规则是按位取反

    ~(0011)= 1100

  • 相关阅读:
    082、Java数组之数组传递之简化理解
    081、Java数组之数组传递
    080、Java数组之二维数组的定义及使用
    079、Java数组之数组的静态初始化
    078、Java数组之数组的引用传递
    077、Java数组之分步实现数组操作
    076、Java数组之定义数组
    075、Java面向对象之定义匿名对象
    074、Java面向对象之构造方法重载
    073、Java面向对象之利用构造方法为属性赋值
  • 原文地址:https://www.cnblogs.com/ouym/p/8809063.html
Copyright © 2011-2022 走看看