环境
为什么要做js位运算呢?
- 由于近期在学习培训hash算法,里边使用了大批量的位运算
- 此外网站也找了许多材料,但大多数较为片面性,并没有表明特殊情况时的解决,换多组数据信息数值就出差错。
追忆整数
ECMAScript 整数有三种种类,即:
- 有符号整数(容许用正数和负数)
- 无符号整数(只允许用正数) 在 ECMAScript 中,全部整数字面量默认设置全是有符号整数,这代表着什么?
有符号整数应用 31 位表明整数的标值,用第 32 位表明整数的符号,0 表示正数,1 表明负数。
标值范畴从 -2147483647 到 2147483647。
位运算会把二进制数限定在32位,超过一部分会被放弃
调节位运算常见的好多个方式
toString(2)
转化成2进制字符串数组
var a = 1732584193;
a.toString(2); // 1100111010001010010001100000001
parseInt(‘11001’, 2)
将2进制字符串转化成10进制数
parseInt(\'11001\', 2) // 25
padStart(32, ‘0’)
字符串数组总长,左侧不够十位数补0
\'1100000001\'.padStart(32, 0) // 00000000000000000000001100000001
源代码、反码、补码
源码
将数据转换成的2进制数, 最左侧表明符号位,1负数,0正数
5 源代码: 0101
-10 源码:11010
反码
正数的反码与其说原码同样
负数的反码,除符号位外,别的位取反
5
源代码:0101
反码:0101
-10
源码:11010
反码:10101
补码
正整数的补码与其说原码同样
负整数的补码,取反码 1
5
源代码:0101
补码:0101
-10
源码:11010
补码:10110
ok,从现在起主题
位运算符
- 非(~)
- 与(&)
- 或(|)
- 异或运算(^)
- 带符号偏移(<<)
- 带符号右移(>>)
- 无符号偏移(>>>)
位运算符:非(~)
计算流程:
- 将该数据取负数
- 随后减1
~25 // -26
全过程:
- 25取负:-25
- 减1:-26
~1 // -2
~-1 // 0
~100 // -101
~-100 // 99
位运算符:与(&)
计算流程:
- 把两个数转化成2进制补码
- 同样部位开展较为(同是1,结论为1,不然为0)
- 假如数值是负数,还需要再做补码解决
假如十位数不足,正数左侧补0,负数补1
真正计算
10 & 3 // 2
全过程:
- 10 补码:1010
- 3 补码:0011
- 结论:0010,即 2
正负极计算(1)
14 & -13 // 2
全过程:
- 14 补码:01110(补一位符号位)
- -13 源代码:11101,补码:10011
- 与运算:00010,即 2
正负极计算(2)
88 & -19 // 72
全过程:
- 88 补码:01011000(补一位符号位)
- -19 源代码:110011,补码:101100
- 01011000 & 101100
- 负数(101100)十位数不足,左侧补1,即11101100
- 也就是 01011000 & 11101100
- 结论为:01001000,即:72
负负计算
-12 & -5 // -16
全过程:
- -12 补码:10100
- -5 补码:11011
- 与运算:10000
- 结论为负,再取一次补码: 110000:-16
训练
3 & 7
-21 & 16
-271733879 & -1732584194
1125899778533470 & 812930
20 & 0xF
48192342 & 0xFFFF
位运算符:或(|)
计算流程:
- 把2个数据转换成2进制补码
- 同样部位开展较为(有一个是1,结论即是1)
- 假如数值是负数,还需要再做补码解决
真正计算
10 | 3 // 11
全过程:
- 10 源代码:1010
- 3 源码:0011
- 结论:1011,即 11
正负极计算
10 | -3 // -1
全过程:
- 10补码:01010
- -3补码:11101
- 或运算:11111
- 结论为负,再取码:10001,即:-1
负负计算
-15 | -21 // -5
全过程:
- -15 补码:110001
- -21 补码:101011
- 或运算:111011
- 结论为负再取补码:10101,即:-5
训练
15 | 20
40 | -14
-271733879 | 1732584193
(-271733879 & -1732584194) | (~-271733879 & 271733878)
位运算符:异或运算(^)
计算流程:
- 把两个数转化成2进制补码
- 同样部位开展较为(务必是0和1或是1和0,结论才为1)
- 假如结论为负,再取补码
真正异或运算
10 ^ 3 // 9
全过程:
- 10 补码:1010
- 3 补码:0011
- 结论:1001,即 9
正负极异或运算
10 ^ -3 // -9
全过程:
- 10 补码: 01010
- -3 补码:11101
- 异或运算:10111
- 结论为负,再取补码:11001,即-9
负负异或运算
-10 ^ -3 // 11
全过程:
- -10 补码:10110
- -3 补码:11101
- 异或运算:01011,即:11
训练
5 ^ 8
-10 ^ 9
-13 ^ -20
-271733879 ^ -1732584194 ^ 271733878
位运算符:带符号偏移(<<)
计算流程:
- 把数据转换成2进制补码
- 偏移特定十位数,右侧补0
- 假如结论未负数,再取补码
超出32位的一部分放弃
正数偏移
1 << 2 // 补码:00000001 左移2位, 即 00000100,结论为:4
5 << 3 // 补码:00000101 偏移3位, 即 00101000,结论为:40
可以看得出,正数带符号偏移,即 a << n,实际上是 a * 2的n次幂
负数偏移
-3 << 4
- -3 补码:101
- 左移4位 1010000
- 标志位为负,取补码:1110000,即-48
-6 << 3 // 1010 << 3 相当于 1010000,取补码,1110000 即:-48
-11 << 4 // 10101 << 4 等于 101010000,取补码,110110000 即:-176
边沿状况
情况1:正数变负数
1732584193 << 2 // -1659597820
测算全过程
- 1732584193转化成2进制源代码:1100111010001010010001100000001(31位)
- 偏移2位,补2个0:110011101000101001000110000000100(33位)
- 清除左侧不必要的1位:10011101000101001000110000000100(32位)
- 变成负数,取补码:11100010111010110111001111111100
- 即:-1659597820
状况2:负数变正数
-1732584193 << 2 // 1659597820
测算全过程
- -1732584193转化成2进制:11100111010001010010001100000001(32位)
- 负数,取补码:10011000101110101101110011111111(32位)
- 偏移2位:1001100010111010110111001111111100(34位)
- 不必要一部分放弃:01100010111010110111001111111100(32位)
- 标记位是正,不用再补码,即:1659597820
训练
1 << 32
1 << 33
1 << 40
2147483648 << 2
1732584193 << 6
位运算符:带符号偏移(>>)
计算流程:
- 取数据二进制补码
- 偏移特定十位数,左侧补位与标记位一致
- 不必要位被放弃
- 假如数值为负,再取补码
正数偏移
5 >> 1 // 0101 右移1位 0010,即 2
1 >> 2 // 0001 偏移1位 0000,即 0
正数右移非常简单,移出来的信息立即放弃就可以,左侧用0填补
负数偏移
-5 >> 2 // -2
剖析:
- -5 补码:1011
- 偏移2位:1110
- 结论为负,取补码:1010,即-2
训练
5 64 >> 9
1732584193 >> 4
位运算符:无标记偏移(>>>)
计算流程:
- 把数据转换成32位2进制补码
- 连着标记位,右挪动特定的十位数
- 往右边被移出来的位被丢掉,左边用0添充
因为符号位变成了 0,因此结论一直正的
正数偏移
正数情况下 >> 和 >>> 结论是一样的
5 >> 2 // 101 偏移2位 001 即:1
5 >>> 2 // 101 右移2位 001 即:1
负数偏移
-5 >>> 2 // 1073741822
全过程:
- -5 源代码: 10000000 00000000 00000000 00000101
- 补码:11111111 11111111 11111111 11111011
- 偏移二位:00111111 11111111 11111111 11111110
- 转化成十进制即是:1073741822
问题:为什么这一要补满32位,而以前的计算也没有?
由于先前的计算,正数补的全是0,负数尽管补1,但测算后要做补码,补位的数最后不危害测算
而无标记偏移,则会危害计算。因此必须补齐
训练
-23 >>> 2
45678765 >>> 31
有关位运算的主要构思
- 计算前要用补码
- 计算结论造成负数,再取一次补码
以上内容全是本人搜集、及其多次试着梳理的。
由于在网上看见的许多文章内容计算方式也不对,尽管举的事例没什么问题,但换发电机组数据就计算误差。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。