位图操作,setbit ,bitcount,bitfield

<?phpfunction 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,01110000Array(    [0] => 1    [1] => 2    [2] => 3    [3] => 9    [4] => 10    [5] => 12    [6] => 17    [7] => 18    [8] => 19)

01110000,01101000,01110000

1,2,3,9,10,12,17,18,19 共9位需设置为1

127.0.0.1:0>get pnull127.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 和位图查找指令 bitpos

  • bitcount 用来统计指定位置范围内 1 的个数
  • bitpos 用来查找指定范围内出现的第一个 0 或 1

bitcount,bitpos

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

bitfield(3.2版本之后) 有三个子指令,分别是 get/set/incrby,它们都可以对指定位片段进行读写,但是最多只能处理 64 个连续的位,如果超过 64 位,就得使用多个子指令,bitfield 可以一次执行多个子指令

php

01110000,01101000,01110000

127.0.0.1:6379> get p"php"127.0.0.1:6379> bitfield p get u4 0  # 从第0个位开始取4个位  即为 0111  结果是无符号数 (u)1) (integer) 7127.0.0.1:6379> bitfield p get u3 2  #从第2个位开始取3个位 即为110结果是无符号数 (u)1) (integer) 6127.0.0.1:6379> bitfield p get i4 0  #从第0个位开始取4个位即为0111结果是有符号数 (i)1) (integer) 7127.0.0.1:6379> bitfield p get i3 2  #从第2个位开始取3个    即为110结果是有符号数 (i)1) (integer) -2127.0.0.1:6379> bitfield p  get u4 0  get u3 2  get i4 0     get i3 21) (integer) 72) (integer) 63) (integer) 74) (integer) -2

所谓有符号数是指获取的位数组中第一个位是符号位,剩下的才是值
如果第一位是 1,那就是负数
无符号数表示非负数,没有符号位,获取的位数组全部都是值。有符号数最多可以获取 64 位,无符号数只能获取 63 位 (因为 Redis 协议中的 integer 是有符号数,最大 64 位,不能传递 64 位无符号值)
如果超出位数限制,Redis 就会告诉你参数错误

01110000,01101000,01110000把第二个h这只为p只需要把第11位由0->1,第12位由1->0即可setbit p 11 1setbit p 12 0127.0.0.1:6379> setbit p 11 1(integer) 0127.0.0.1:6379> setbit p 12 0(integer) 1127.0.0.1:6379> get p"ppp"127.0.0.1:6379> set p phpOK127.0.0.1:6379> bitfield p set u8 8 97  #从第 8 个位开始,将接下来的 8 个位用无符号数 97 替换1) (integer) 104127.0.0.1:6379> get p"pap"

incrby

它用来对指定范围的位进行自增操作自增有可能出现溢出
如果增加了正数,会出现上溢,如果增加的是负数,就会出现下溢出

Redis 默认的处理是折返。如果出现了溢出,就将溢出的符号位丢掉
如果是 8 位无符号数 255,加 1 后就会溢出,会全部变零。如果是 8 位有符号数 127,加 1 后就会溢出变成 -128

bitfield p incrby u7 1 1127.0.0.1:6379> set p phpOK127.0.0.1:6379> bitfield p incrby u7 1 1  # 从第7位开始,对接下来的1位无符号数 +11) (integer) 113127.0.0.1:6379> get p"qhp"127.0.0.1:6379> bitfield p incrby u7 1 11) (integer) 114       #r 的ascii码 为114127.0.0.1:6379> get p"rhp"127.0.0.1:6379> set  p phpOK127.0.0.1:6379> bitfield p incrby u1 1 11) (integer) 0127.0.0.1:6379> get p"0hp"127.0.0.1:6379> bitfield p incrby u1 1 11) (integer) 1127.0.0.1:6379> get p"php"

bitfield 指令提供了溢出策略子指令

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 11) (integer) 15127.0.0.1:6379> get p"x"127.0.0.1:6379> bitfield p overflow sat incrby u4 1 11) (integer) 15127.0.0.1:6379> get p"x"127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1 ## 保持最大值1) (integer) 15127.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 pOK127.0.0.1:6379> bitfield p overflow fail incrby u5 1 11) (integer) 29127.0.0.1:6379> get p"t"127.0.0.1:6379> bitfield p overflow fail incrby u5 1 11) (integer) 30127.0.0.1:6379> get p"x"127.0.0.1:6379> bitfield p overflow fail incrby u5 1 11) (integer) 31127.0.0.1:6379> get p"|"127.0.0.1:6379> bitfield p overflow fail incrby u5 1 11) (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即为字符 |

再继续执行就会溢出,所以保留当前的最大值

©著作权归作者所有:来自51CTO博客作者hkui2010的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. URL百分比编码与符号字符
  2. 2021-03-27:给你一个链表的头节点 head ,旋转链表,将链表每个节点向
  3. 加入其他控制变量后, 估计系数的符号相反了?
  4. SQL如何实现Excel的分列功能(按指定符号进行分割)?
  5. 数据的储存(一)(整形)(零基础学习C语言)
  6. C编程基础-基础篇 2
  7. 关于Android(安卓)Studio开发环境变量的设置(avd启动黑屏)
  8. Android(安卓)特殊符号的转码大全
  9. 宏定义中的特殊参数(#、##、...和__VA_ARGS__)

随机推荐

  1. 如何使用XMLHttpRequest向服务器发送数组
  2. jquery validate和jquery form 插件组合
  3. 使用jquery ajax代替iframe
  4. 在没有重新设置源选项的情况下,使用x-edit
  5. 函数的作用是:显示内联块。如何?
  6. 前台jquery+ajax向后台请求数据,后台返回j
  7. 使用js和ajax从django服务器检索数据
  8. 如何删除/更改JQuery UI自动完成帮助文本
  9. jQuery的deferred对象详解
  10. js和jquery使按钮失效为不可用状态的方法