<?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 )
<p style='font-size:28px;font-style:italic;color:rgb(120,0,160)'>01110000,01101000,01110000</p> <p style='color:red;font-size:20px;'>1,2,3,9,10,12,17,18,19 共9位需设置为1</p>php
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"
<h1> 统计和查找</h1> Redis 提供了位图统计指令 bitcount 和位图查找指令 bitpos 数组
- bitcount 用来统计指定位置范围内 1 的个数
- bitpos 用来查找指定范围内出现的第一个 0 或 1
<h3 style='color:blue'>bitcount,bitpos</h3>spa
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"
<h1 style="color:blue">bitfield</h1>code
bitfield(3.2版本以后) 有三个子指令,分别是 get/set/incrby,它们均可以对指定位片断进行读写,可是最多只能处理 64 个连续的位,若是超过 64 位,就得使用多个子指令,bitfield 能够一次执行多个子指令ci
phpget
<p style='font-weight:bolder;font-style:italic;font-size:22px;color:rgb(20,120,20)'>01110000,01101000,01110000</p>it
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"
incrby
它用来对指定范围的位进行自增操做自增有可能出现溢出
若是增长了正数,会出现上溢,若是增长的是负数,就会出现下溢出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"
bitfield 指令提供了溢出策略子指令
overflow,用户能够选择溢出行为,默认是折返 (wrap),还能够选择失败 (fail) 报错不执行,以及饱和截断 (sat),超过了范围就停留在最大最小值 overflow 指令只影响接下来的第一条指令,这条指令执行完后溢出策略会变成默认值折返 (wrap)
<p style="color:red;font-weight:bolder;font-size:24px;"> 饱和截断 SAT</p> p的二进制 <p style='color:blue;font-size:24px;'>0111 0000</p>
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"
对
<p style='color:blue;font-size:24px;'>0111 0000</p> 执行
bitfield p overflow sat incrby u4 1 1
后变为
<p style='color:green;font-size:24px;'>0111 1000</p> 继续
bitfield p overflow sat incrby u4 1 1
由于采起了截断 (sat),超过了范围就停留在最大最小值
<p style="color:red;font-weight:bolder;font-size:24px;"> 失败不执行 FAIL SAT</p>
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>
过程分析
对
<p style='color:blue;font-size:24px;'>0111 0000</p> 执行
bitfield p overflow fail incrby u5 1 1
变为
<p style='color:green;font-size:24px;'>0111 0100</p> ascii码为116 即为字符t
而后继续执行
bitfield p overflow fail incrby u5 1 1
<p style='color:orange;font-size:24px;'>0111 1000</p> ascii为120即为字符 x
而后继续执行
bitfield p overflow fail incrby u5 1 1
变为
<p style='color:rgb(200,0,100);font-size:24px;'>0111 1100</p> ascii 124即为字符 |
再继续执行就会溢出,因此保留当前的最大值