位運算及其應用場景

概念理解
  • 按位與 & :全1為1折砸,有0為0

假設 1:true,0:false沙峻,聯(lián)想Java中的&&運算符睦授,只有兩個都為true才為true,其他均為false
&舉例:
0000 0011
0000 1010
==============
0000 0010

  • 按位或 | :有1為1摔寨,全0為0

假設 1:true去枷,0:false,聯(lián)想Java中的||運算符是复,只有有一個為為true就為true删顶,全為false才為false
| 舉例:
0000 0011
0000 1010
==============
0000 1011

  • 按位異或 ^ :不同為1,相同為0

假設1為男性淑廊,0為女性逗余,異性相吸修成正果則為1,同性相斥孤獨終老為0
^ 舉例:
0000 0011
0000 1010
==============
0000 1001

按位非:~ :按位取反季惩,1為0录粱,0為1

~ 舉例:
0000 0011 ~
==============
1111 1100

  • 有符號左移 << :各二進位全部左移若干位,高位丟棄画拾,低位補0
    若左移時舍棄的高位不包含1啥繁,則每左移一位,相當于該數乘以2
    a = a << 2 = a + 2的2次方

舉例:
0000 1101 =
<< 2位
====================
0011 0100

  • 有符號右移 >> :將一個數的各二進制位全部右移若干位青抛,正數左補0旗闽,負數左補1,右邊丟棄蜜另。
    操作數每右移一位适室,相當于該數除以2。
    a = a >> 2 相當于 a除以2的2次方

舉例:
0000 1101 =
>> 2位
====================
0000 0011 = 3

  • 無符號右移 >>> :將一個數的各二進制位全部右移若干位蚕钦,高位補0
// 1010
System.out.println("10 = " + Integer.toBinaryString(10));

// 0110
System.out.println("6 = " + Integer.toBinaryString(6));

// 按位與: 1&1=1 1&0 = 0 0&1=0 0&0=0
// 0010
System.out.println("10 & 6 = " + Integer.toBinaryString(10 & 6));

// 按位或:1&1=1 1&0=1 0&1=1 0&0=0
// 1110
System.out.println("10 | 6 = " + Integer.toBinaryString(10 | 6));

// 按為異或:1&1=0 1&0=1 0&1=1 0&0=0
// 1100
System.out.println("10 ^ 6 = " + Integer.toBinaryString(10 ^ 6));


// 左移
int a = 10;
// 1010 <<2 = 0010 1000
// 40 = 10 * 2 ^ 2
System.out.println("a << 2 = " + (a << 2));
// 0010 1000
System.out.println("a << 2 = " + Integer.toBinaryString((a << 2)));

// 右移
int b = 101;
// 0110 0101
System.out.println("b = " + Integer.toBinaryString(101));
// 101 / 2^2 = 25
System.out.println("b >> 2 = " + (b >> 2));
// 0001 1001
System.out.println("b >> 2 = " + Integer.toBinaryString((b >> 2)));
應用場景

1亭病、取模

當一個數a除以 2的n次方求余數時,(a / 2^n)等價于 a & (2^n - 1)
原理:某個數A嘶居,對 2^n 取模,則余數最大值為 2^n-1 ,當按位與上 2^n-1 時邮屁,高位的都被舍棄整袁,只留下了2^n-1中滿足條件的余數

/**
 * 如果取模的分母是2的N次方,則等價于 &上2的N次方-1
 * b % 4 = b & (2 ^2 - 1)
 * b = 101
 *   0110 0101
 * & 0000 0011
 * ---------------
 *   0000 0001
 *
 *   b = 111 % 16 = 15
 *
 *   0110 1111
 *   0000 1111
 *   ------------
 *   0000 1111
 *
 */
// 1
int b = 101;
System.out.println("b % 4 = " + (b % 4) + " = " + (b & (4 - 1)));
b = 111;
// 15
System.out.println("b % 16 = " + (b % 16) + " = " + (b & (16 - 1)));

2佑吝、保存操作狀態(tài)或商品屬性開關

權限控制坐昙,有增刪改查四種權限,傳統(tǒng)意義上會在新增四個屬性分別對應四種權限芋忿,如果有再新增權限的話炸客,又要新增屬性
在這種情況下,可以使用位戈钢,一個int類型有32位痹仙,理論上可以存儲32個屬性、狀態(tài)

/**
 * 權限操作類
 */
public class Permissions {

    /**
     * 二進制第1位是否允許查詢殉了,0表示否开仰,1表示是
     * 1 << 0 = 0001  = 1
     */
    public static final int ALLOW_SELECT = 1 << 0;

    /**
     * 二進制第2位是否允許新增,0表示否薪铜,1表示是
     * 1 << 1 = 0010  = 2
     */
    public static final int ALLOW_INSERT = 1 << 1;

    /**
     * 二進制第3位是否允許修改众弓,0表示否,1表示是
     * 1 << 2 = 0100 = 4
     */
    public static final int ALLOW_UPDATE = 1 << 2;

    /**
     * 二進制第4位是否允許刪除隔箍,0表示否谓娃,1表示是
     * 1 << 3 = 1000 = 8
     */
    public static final int ALLOW_DELETE = 1 << 3;


    /**
     * 目前所擁有的權限狀態(tài)
     */
    private int flag;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    /**
     * 新增1個或者多個權限
     * 按位或,有1為1蜒滩,全0為0傻粘,按位或后有1的位置全都有了權限
     */
    public void addPermission(int flag) {
        this.flag = this.flag | flag;
    }

    /**
     * 刪除1個或多個權限
     * 先按位取反,這樣不需要刪除的位置為1帮掉,刪除的位置為0弦悉,在按位與,將對于為0的位置置0
     *
     */
    public void removePermission(int flag) {
        this.flag = this.flag & ~flag;
    }

    /**
     * 是否有某個操作的權限
     * 先按位與后如果操作位對應的是1蟆炊,則操作位繼續(xù)為1渔呵,否則全為0,得到的結果要么為flag小槐,要么全為0
     */
    public boolean hasPermission(int flag) {
        return (this.flag & flag) == flag;
    }

    public boolean hasNotPermission(int flag) {
        return (this.flag & flag) == 0;
    }

    /**
     * flag : 0, insert : false
     * flag : 0, delete : false
     * flag : 0, update : false
     * flag : 0, select : false
     * 添加查詢權限
     * flag : 1, insert : false
     * flag : 1, delete : false
     * flag : 1, update : false
     * flag : 1, select : true
     * 添加修改權限
     * flag : 5, insert : false
     * flag : 5, delete : false
     * flag : 5, update : true
     * flag : 5, select : true
     * 添加刪除權限
     * flag : 13, insert : false
     * flag : 13, delete : true
     * flag : 13, update : true
     * flag : 13, select : true
     * 添加插入權限
     * flag : 15, insert : true
     * flag : 15, delete : true
     * flag : 15, update : true
     * flag : 15, select : true
     * 去掉查詢權限
     * flag : 14, insert : true
     * flag : 14, delete : true
     * flag : 14, update : true
     * flag : 14, select : false
     * 去掉修改權限
     * flag : 10, insert : true
     * flag : 10, delete : true
     * flag : 10, update : false
     * flag : 10, select : false
     * 去掉刪除權限
     * flag : 2, insert : true
     * flag : 2, delete : false
     * flag : 2, update : false
     * flag : 2, select : false
     * 去掉插入權限
     * flag : 0, insert : false
     * flag : 0, delete : false
     * flag : 0, update : false
     * flag : 0, select : false
     */
    public static void main(String[] args) {
        // 默認沒有任何權限
        int flag = 0;
        Permissions permissions = new Permissions();
        permissions.setFlag(flag);
        permissions.print(permissions);
        // 添加查詢權限
        System.out.println("添加查詢權限");
        permissions.addPermission(Permissions.ALLOW_SELECT);
        permissions.print(permissions);
        // 添加修改權限
        System.out.println("添加修改權限");
        permissions.addPermission(Permissions.ALLOW_UPDATE);
        permissions.print(permissions);
        // 添加刪除權限
        System.out.println("添加刪除權限");
        permissions.addPermission(Permissions.ALLOW_DELETE);
        permissions.print(permissions);
        // 添加插入權限
        System.out.println("添加插入權限");
        permissions.addPermission(Permissions.ALLOW_INSERT);
        permissions.print(permissions);

        // 去掉查詢權限
        System.out.println("去掉查詢權限");
        permissions.removePermission(Permissions.ALLOW_SELECT);
        permissions.print(permissions);

        // 去掉修改權限
        System.out.println("去掉修改權限");
        permissions.removePermission(Permissions.ALLOW_UPDATE);
        permissions.print(permissions);

        // 去掉刪除權限
        System.out.println("去掉刪除權限");
        permissions.removePermission(Permissions.ALLOW_DELETE);
        permissions.print(permissions);

        // 去掉插入權限
        System.out.println("去掉插入權限");
        permissions.removePermission(Permissions.ALLOW_INSERT);
        permissions.print(permissions);
    }

    private void print(Permissions permissions) {
        System.out.println("flag : " + permissions.getFlag() + ", insert : " + permissions.hasPermission(Permissions.ALLOW_INSERT));
        System.out.println("flag : " + permissions.getFlag() + ", delete : " + permissions.hasPermission(Permissions.ALLOW_DELETE));
        System.out.println("flag : " + permissions.getFlag() + ", update : " + permissions.hasPermission(Permissions.ALLOW_UPDATE));
        System.out.println("flag : " + permissions.getFlag() + ", select : " + permissions.hasPermission(Permissions.ALLOW_SELECT));
    }

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末皂股,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子昧甘,更是在濱河造成了極大的恐慌良拼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件充边,死亡現場離奇詭異庸推,居然都是意外死亡常侦,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門贬媒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聋亡,“玉大人,你說我怎么就攤上這事际乘∑戮螅” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵脖含,是天一觀的道長罪塔。 經常有香客問我,道長养葵,這世上最難降的妖魔是什么征堪? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮港柜,結果婚禮上请契,老公的妹妹穿的比我還像新娘。我一直安慰自己夏醉,他們只是感情好爽锥,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著畔柔,像睡著了一般氯夷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上靶擦,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天腮考,我揣著相機與錄音,去河邊找鬼玄捕。 笑死踩蔚,一個胖子當著我的面吹牛,可吹牛的內容都是我干的枚粘。 我是一名探鬼主播馅闽,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼馍迄!你這毒婦竟也來了福也?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤攀圈,失蹤者是張志新(化名)和其女友劉穎暴凑,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體赘来,經...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡现喳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年凯傲,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拿穴。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡泣洞,死狀恐怖忧风,靈堂內的尸體忽然破棺而出默色,到底是詐尸還是另有隱情,我是刑警寧澤狮腿,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布腿宰,位于F島的核電站,受9級特大地震影響缘厢,放射性物質發(fā)生泄漏吃度。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一贴硫、第九天 我趴在偏房一處隱蔽的房頂上張望椿每。 院中可真熱鬧,春花似錦英遭、人聲如沸间护。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汁尺。三九已至,卻和暖如春多律,著一層夾襖步出監(jiān)牢的瞬間痴突,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工狼荞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辽装,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓相味,卻偏偏與公主長得像拾积,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子攻走,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內容

  • 在Java中殷勘,位運算符有:與(&)、非(~)昔搂、或(|)玲销、異或(^)、移位(<< 和 >>)摘符、無符移位(<<< 和 ...
    一笑小先生閱讀 3,848評論 0 3
  • 簡介 梳理一下位運算定義贤斜、數學意義以及它的應用場景策吠,在日常編碼中能給我們帶來什么提升。 運算定義 了解原碼反碼和補...
    勤勞的熊熊閱讀 5,291評論 0 3
  • 內容概要: 位運算基本操作 基于位運算的狀態(tài)壓縮 位運算經典應用 位運算解N皇后問題 位運算 符號描述規(guī)則&與1&...
    Ice_spring閱讀 964評論 0 2
  • 計算機中的數在內存中都是以二進制形式進行存儲的瘩绒,用位運算就是直接對整數在內存中的二進制位進行操作猴抹,因此其執(zhí)行效率非...
    Lem0nNat1on閱讀 498評論 0 0
  • 謹記: 上帝在締造每個人的時候,給予每個人的一切都是相同的锁荔,然而蟀给,人與人卻是存在如此大的差距,記著上帝為你關上了一...
    長風留言閱讀 4,931評論 0 5