<?php function frstr($str){ return str_pad($str,8,'0',STR_PAD_LEFT); } $php=''; $p= frstr(decbin(ord('p'))); $h= frstr(decbin(ord('h'))); $php=$p.$h.$p; echo $php; echo PHP_EOL; $len=strlen($php); $index=[]; for($i=0;$i<$len;$i++){ if($php[$i]==1){ $index[]=$i; } } print_r($index);
01110000,01101000,01110000 Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 9 [4] => 10 [5] => 12 [6] => 17 [7] => 18 [8] => 19 )
01110000,01101000,01110000php
1,2,3,9,10,12,17,18,19 共9位需設置爲1數組
127.0.0.1:0>get p null 127.0.0.1:0>setbit p 1 1 "0" 127.0.0.1:0>setbit p 2 1 "0" 127.0.0.1:0>setbit p 3 1 "0" 127.0.0.1:0>get p "p" 127.0.0.1:0>setbit p 9 1 "0" 127.0.0.1:0>setbit p 10 1 "0" 127.0.0.1:0>setbit p 12 1 "0" 127.0.0.1:0>setbit p 17 1 "0" 127.0.0.1:0>setbit p 18 1 "0" 127.0.0.1:0>setbit p 19 1 "0" 127.0.0.1:0>get p "php"
Redis 提供了位圖統計指令 bitcount 和位圖查找指令 bitposcode
127.0.0.1:0>bitcount p "9" 127.0.0.1:0>bitcount p 0 0 #第一個字符中1的個數 "3" 127.0.0.1:0>bitcount p 0 1 #前2個字符中1的個數 "6" 127.0.0.1:0>bitpos p 0 #第一個0位 "0" 127.0.0.1:0>bitpos p 1 #第一個1位 "1" 127.0.0.1:0>bitpos p 1 1 1 #從第二個字符算起第一個1位 "9" 127.0.0.1:0>bitpos p 1 2 2 # 從第三個字符算起,第一個 1 位 "17"
bitfield(3.2版本以後) 有三個子指令,分別是 get/set/incrby,它們均可以對指定位片斷進行讀寫,可是最多隻能處理 64 個連續的位,若是超過 64 位,就得使用多個子指令,bitfield 能夠一次執行多個子指令ci
php
get
01110000,01101000,01110000it
127.0.0.1:6379> get p "php" 127.0.0.1:6379> bitfield p get u4 0 # 從第0個位開始取4個位 即爲 0111 結果是無符號數 (u) 1) (integer) 7 127.0.0.1:6379> bitfield p get u3 2 #從第2個位開始取3個位 即爲110 結果是無符號數 (u) 1) (integer) 6 127.0.0.1:6379> bitfield p get i4 0 #從第0個位開始取4個位 即爲0111 結果是有符號數 (i) 1) (integer) 7 127.0.0.1:6379> bitfield p get i3 2 #從第2個位開始取3個 即爲110 結果是有符號數 (i) 1) (integer) -2 127.0.0.1:6379> bitfield p get u4 0 get u3 2 get i4 0 get i3 2 1) (integer) 7 2) (integer) 6 3) (integer) 7 4) (integer) -2
所謂有符號數是指獲取的位數組中第一個位是符號位,剩下的纔是值
若是第一位是 1,那就是負數
無符號數表示非負數,沒有符號位,獲取的位數組所有都是值。有符號數最多能夠獲取 64 位,無符號數只能獲取 63 位 (由於 Redis 協議中的 integer 是有符號數,最大 64 位,不能傳遞 64 位無符號值)
若是超出位數限制,Redis 就會告訴你參數錯誤io
01110000,01101000,01110000 把第二個h這隻爲p 只須要把第11位由0->1,第12位由1->0便可 setbit p 11 1 setbit p 12 0 127.0.0.1:6379> setbit p 11 1 (integer) 0 127.0.0.1:6379> setbit p 12 0 (integer) 1 127.0.0.1:6379> get p "ppp" 127.0.0.1:6379> set p php OK 127.0.0.1:6379> bitfield p set u8 8 97 #從第 8 個位開始,將接下來的 8 個位用無符號數 97 替換 1) (integer) 104 127.0.0.1:6379> get p "pap"
它用來對指定範圍的位進行自增操做自增有可能出現溢出
若是增長了正數,會出現上溢,若是增長的是負數,就會出現下溢出function
Redis 默認的處理是折返。若是出現了溢出,就將溢出的符號位丟掉
若是是 8 位無符號數 255,加 1 後就會溢出,會所有變零。若是是 8 位有符號數 127,加 1 後就會溢出變成 -128class
bitfield p incrby u7 1 1 127.0.0.1:6379> set p php OK 127.0.0.1:6379> bitfield p incrby u7 1 1 # 從第7位開始,對接下來的1位無符號數 +1 1) (integer) 113 127.0.0.1:6379> get p "qhp" 127.0.0.1:6379> bitfield p incrby u7 1 1 1) (integer) 114 #r 的ascii碼 爲114 127.0.0.1:6379> get p "rhp" 127.0.0.1:6379> set p php OK 127.0.0.1:6379> bitfield p incrby u1 1 1 1) (integer) 0 127.0.0.1:6379> get p "0hp" 127.0.0.1:6379> bitfield p incrby u1 1 1 1) (integer) 1 127.0.0.1:6379> get p "php"
overflow,用戶能夠選擇溢出行爲,默認是折返 (wrap),還能夠選擇失敗 (fail) 報錯不執行,以及飽和截斷 (sat),超過了範圍就停留在最大最小值
overflow 指令隻影響接下來的第一條指令,這條指令執行完後溢出策略會變成默認值折返 (wrap)二進制
飽和截斷 SAT
p的二進制
0111 0000
127.0.0.1:6379> get p "p" 127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1 1) (integer) 15 127.0.0.1:6379> get p "x" 127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1 1) (integer) 15 127.0.0.1:6379> get p "x" 127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1 ## 保持最大值 1) (integer) 15 127.0.0.1:6379> get p "x"
對
0111 0000
bitfield p overflow sat incrby u4 1 1
後變爲
0111 1000
bitfield p overflow sat incrby u4 1 1
由於採起了截斷 (sat),超過了範圍就停留在最大最小值
失敗不執行 FAIL SAT
127.0.0.1:6379> set p p OK 127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1 1) (integer) 29 127.0.0.1:6379> get p "t" 127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1 1) (integer) 30 127.0.0.1:6379> get p "x" 127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1 1) (integer) 31 127.0.0.1:6379> get p "|" 127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1 1) (nil) 127.0.0.1:6379> get p "|" 127.0.0.1:6379>
過程分析
對
0111 0000
bitfield p overflow fail incrby u5 1 1
變爲
0111 0100
ascii碼爲116 即爲字符t而後繼續執行
bitfield p overflow fail incrby u5 1 1
0111 1000
ascii爲120即爲字符 x
而後繼續執行
bitfield p overflow fail incrby u5 1 1
變爲
0111 1100
ascii 124即爲字符 |再繼續執行就會溢出,因此保留當前的最大值