”位运算“符进行权限设计

今天在群里听到别人说 位操作能进行权限设计 what ???好奇心就来了 ;立马查资料看看;在这里分享给大家;

什么是位运算

主要是使用到"位运行符"操作,& “与”运算符、|“或“运行符、^ ”异或“位运算符,还有>>“右移”运算符、<<”左移“运算符。参与运算的如果是10进制数,则会被转换至2进制数参与运算,然后计算结果会再转换为10进制数输出。(但是一般10进制对不齐,会写2进制或者16进制的int类型数据)

位运算概况

符号 描述 运算规则
& 两个位都为1时,结果才为1
l 两个位都为0时,结果才为0
^ 异或 两个位相同为0,相异为1
~ 取反 0变1,1变0
<< 左移 各二进位全部左移若干位,高位丢弃,低位补0
>> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)

20=1,相应2进数为"0001"(这里我表示成"次方",即:2的0次方,下同)
2^1=2,相应2进数为"0010"
2^2=4,相应2进数为"0100"
2^3=8,相应2进数为"1000"

下面是常见的运算
1. 与运算(&)

0&0=0 0&1=0 1&0=0 1&1=1

3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1。

  • 常用判断:
  • 1)清零: 3&0
  • 2)取一个数的指定位
  • 3)判断奇偶: if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数

2. 或运算(|)

0|0=0 0|1=1 1|0=1 1|1=1
3|5 即 0000 0011| 0000 0101 = 0000 0111,因此,3|5的值得7。

  • 常用操作
  • 1)常用来对一个数据的某些位设置为1,比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。

3.异或运算(^)

0^0=0 0^1=1 1^0=1 1^1=0

  • 1、交换律
  • 2、结合律 (ab)c == a(bc)
  • 3、对于任何数x,都有 xx=0,x0=x
  • 4、自反性: abb=a^0=a;

4.左移运算符(<<)
定义:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
设 a=1010 1110,a = a<< 2 将a的二进制位左移2位、右补0,即得a=1011 1000。
若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

5.右移运算符(>>)
定义:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
例如:a=a>>2 将a的二进制位右移2位,左补0 或者 左补1得看被移数是正还是负。
操作数每右移一位,相当于该数除以2。

优点

位运算的运算对象是二进制的位,速度快,效率高,而且节省存储空间,位运算做权限控制又相当地灵活。Linux系统的文件权限的实现方式,就是采用了位运算

缺点

位运算也有很大的局限,因为在32位计算机上,位移不能超过32次,这就要求权限数量不超过32种。

示例1

比如后台工具的管理权限

//定于权限 2的n次方
var ADD = 1; // 增加权限
var UPD = 2; // 修改权限
var SEL = 4; // 查找权限
var DEL = 8; // 删除权限

// 给予某种权限用到"位或"运算符
var GROUP_A = ADD | UPD | SEL | DEL; // A 拥有增删改查权限
var GROUP_B = ADD | UPD | SEL; // B 拥有增改查权限
var GROUP_C = ADD | UPD; // C 拥有增改权限

// 禁止某种权限用"位与"和"位非"运算符
$GROUP_D = GROUP_C & ~UPD; // D 只拥有了增权限


//检测某个用户是否有这个权限
console.log("A用户组成员是否有增加权限"+ ((GROUP_A & ADD) > 0))
console.log("A用户组成员是否有删除权限"+ ((GROUP_A & DEL) > 0))

console.log("B用户组成员是否有增加权限"+ ((GROUP_B & ADD) > 0))
console.log("B用户组成员是否有删除权限"+ ((GROUP_B & DEL) > 0))

console.log("C用户组成员是否有增加权限"+ ((GROUP_C & ADD) > 0))
console.log("C用户组成员是否有删除权限"+ ((GROUP_C & DEL) > 0))

console.log("D用户组成员是否有增加权限"+ ((GROUP_C & ADD) > 0))
console.log("D用户组成员是否有删除权限"+ ((GROUP_C & DEL) > 0))

示例2

在Linux文件系统中,一个用户对文件或目录所拥有的权限分为三种:“可读”、“可写"和"可执行”,分别用 1 、2 和 4 来表示,它们之间可以任意组合:有"可读"、“可写"权限就用 3 来表示(1 + 2 = 3);有"可读”、"可执行"权限就用5来表示(1 + 4 = 5),三种权限全部拥有就用 7 表示(1 + 2 + 4 = 7)
实际上,这种运算是基于二进制的。

在这里插入图片描述
假设可执行、可写、可读三种权限分别对应三个状态位,如果用户具有某种权限,那么将对应的状态位标识为"1",反之则标识为"0"

代码示例

//定义权限
var READ = 1<< 0; // 把可读权限放在最右边
var WRITE = 1<<1; // 可读权限向左移一位
var EXCUTE = 1<<2; // 可执行权限向左移两位

//赋予权限
var USER_TYL = READ | WRITE; //设置权限读和写

//验证权限
console.log("USER_TYL可读:"+ ((USER_TYL & READ) > 0));
console.log("USER_TYL可写:"+ ((USER_TYL & WRITE) > 0));
console.log("USER_TYL可执行:"+ ((USER_TYL & EXCUTE) > 0));

总结

案例只是简单的应用、一般项目中还是会写2进制或者16进制的int类型数据;
如:0x0001

如:

var ADD = 0x0001; // 增加权限
var UPD = 0x0011; // 修改权限
var SEL = 0x0111; // 查找权限
var DEL = 0x1111; // 删除权限
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章