添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
痴情的橙子  ·  javascript 取得按钮 ...·  1 周前    · 
聪明伶俐的课本  ·  SQL ...·  1 年前    · 

虽然当时知道这是位运算符,但是对他的原理以及运算的结果还是有点不太清楚,遂搜集资料,整理了这篇文章

其实上面代码可以转化为:

let x = Math.floor((m + n) / 2)

逻辑运算符

运算符名称描述
&AND如果两位都是 1 则设置每位为 1
|OR如果两位之一为 1 则设置每位为 1
XOR如果两位只有一位为 1 则设置每位为 1
~NOT反转所有位
<<零填充左位移通过从右推入零向左位移,并使最左边的位脱落。
>>有符号右位移通过从左推入最左位的拷贝来向右位移,并使最右边的位脱落。
>>>零填充右位移通过从左推入零来向右位移,并使最右边的位脱落。
  • 在Javascript中使用位运算符,底层会先将数字转为整数(因为JS中所有的数字都保存为双精度浮点数),然后再进行计算(比如经常利用位运算符取整)
  • 位运算直接对二进制位进行计算(即按照内存中表示数值的位来操作数值),直接处理每一个比特位
  • 位操作符并不直接操作64位的值。而是先将64位的值转换为32位的整数,再执行操作,最后再将结果转换为64位
  • 对于有符号的整数,32位中的后31位用于表示整数的值,第1位表示数值的符号:0表示正数,1表示负数。

    假如有一个值为55转换成二进制为 101 ,转换过程:

    但是因为它占用4字节(32位),所以前面填了一堆0,即 00000000 00000000 00000000 00000101

    那么 -5 呢?

    在计算机中,负数是以其正值的补码形式来表达的,如下

    原码:一个整数,按照绝对值大小转换成的二进制数,称为原码
    比如:5 的原码为 00000000 00000000 00000000 00000101
    反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码(1变0,0变1)
    比如:5 的反码为 11111111 11111111 11111111 11111010
    补码:反码加 1 称为补码
    比如:5 的补码为 11111111 11111111 11111111 11111011
    

    正数以纯二进制格式存储,31位中的每1位都表示2的幂(还有1位是符号位)。第一位表示2º,第二位表示2¹,第三位表示2²,以此类推。没有用到的位以0表示(即忽略不计)。

    负数同样以二进制码存储,但使用的格式是二进制补码。计算一个数值的二进制补码(即求一个负数的二进制码),需要经过下列3个步骤:

  • 求这个数值绝对值的二进制码
  • 求二进制反码,即将0替换为1,将1替换为0
  • 得到的二进制反码+1
  • 按位 与(AND):&

    & 以 特定的方式 组合操作 二进制 数中对应的位, 如果对应的位都为1,那么结果就是1。如果任意一个位是0,则结果就是0

    1 的二进制:00000000 00000000 00000000 00000001
    2 的二进制:00000000 00000000 00000000 00000010
    1 & 2 最终结果(也就是0):00000000 00000000 00000000 00000000
    1 的二进制:00000000 00000000 00000000 00000001
    3 的二进制:00000000 00000000 00000000 00000011
    1 & 3 最终结果(也就是1):00000000 00000000 00000000 00000001
    

    按位 或(OR):|

    | 运算符跟 & 的区别在于如果对应的位中任一个操作数为1,那么结果就是1

    1 的二进制:00000000 00000000 00000000 00000001
    2 的二进制:00000000 00000000 00000000 00000010
    1 | 2 最终结果(也就是3):00000000 00000000 00000000 00000011
    1 的二进制:00000000 00000000 00000000 00000001
    3 的二进制:00000000 00000000 00000000 00000011
    1 | 3 最终结果(也就是3):00000000 00000000 00000000 00000011
    

    按位 异或(XOR):^

    ^ 如果对应两个操作位 有且仅有1个1时结果为1,其它都是0

    1 的二进制:00000000 00000000 00000000 00000001
    2 的二进制:00000000 00000000 00000000 00000010
    1 ^ 2 最终结果(也就是3):00000000 00000000 00000000 00000011
    1 的二进制:00000000 00000000 00000000 00000001
    3 的二进制:00000000 00000000 00000000 00000011
    1 ^ 3 最终结果(也就是2):00000000 00000000 00000000 00000010
    

    按位 非(NOT):~

    ~ 运算符是对位求反,1变0,0变1,也就是求二进制的反码

    2 的二进制:00000000 00000000 00000000 00000010
    反码:11111111 11111111 11111111 11111101
    由于第一位(符号位)是1,所以这个数是一个负数。
    JavaScript 内部采用补码形式表示负数,即需要将这个数减去1,再取一次反,然后加上负号,才能得到这个负数对应的10进制值。
    反码 -1
    11111111 11111111 11111111 11111100
    00000000 00000000 00000000 00000011
    ~2 的最终结果:-3
    3 的二进制:00000000 00000000 00000000 00000011
    反码:11111111 11111111 11111111 11111100
    反码 -1
    11111111 11111111 11111111 11111011
    00000000 00000000 00000000 00000100
    ~3 的最终结果:-4
    

    左移(Left shift):<<

    << 运算符使指定的二进制数所有位都左移指定次数,其移动规则为:丢弃高位,低位补0(即按照二进制形式把所有的数字向左移动对应的位数,高位移除(舍弃),低位的空位补0)

    1 的二进制:00000000 00000000 00000000 00000001
    1 << 2 (即左移2位)
         00000000 00000000 00000000 00000001
       00000000 00000000 00000000 0000000100
    抛弃向左移动的两个0,后面补0,结果二进制如下
         00000000 00000000 00000000 00000100
    1 << 2 的最终结果:4
    1 << 3 (即左移3位)
         00000000 00000000 00000000 00000001
      00000000 00000000 00000000 00000001000
    抛弃向左移动的三个0,后面补0,结果二进制如下
         00000000 00000000 00000000 00001000
    1 << 3 的最终结果:8
    

    M << N,相当于:M * (2**N)

    有符号右移:>> (又称 “符号传播”)

    >> 该操作符会将指定操作数的二进制位向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧(这里是和无符号右移的最大区别)。由于新的最左侧的位总是和以前相同,而符号位并没有被改变。所以被称作“符号传播”

    3 的二进制:00000000 00000000 00000000 00000011 00000000 00000000 00000000 00000011 00000000 00000000 00000000 00000011 拷贝最前面两位00,抛弃向右移除的两位11,结果二进制如下 00000000 00000000 00000000 00000000 3 >> 2 最终结果:0 4 的二进制:00000000 00000000 00000000 00000100 00000000 00000000 00000000 00000100 00000000 00000000 00000000 00000100 拷贝最前面一位0,抛弃向右移除的一位0,结果二进制如下 000000000 00000000 00000000 0000010 4 >> 1 最终结果:2

    无符号右移:>>>

    该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充(这点是和有符号右移最大的区别)。因为符号位变成了0,所以结果总是非负的。

    注:对于非负数,有符号右移和无符号右移总是返回相同的结果。

    3 的二进制:00000000 00000000 00000000 00000011 00000000 00000000 00000000 00000011 00000000 00000000 00000000 00000011 拷贝最前面两位00,抛弃向右移除的两位11,结果二进制如下 00000000 00000000 00000000 00000000 3 >>> 2 最终结果:0 4 的二进制:00000000 00000000 00000000 00000100 00000000 00000000 00000000 00000100 00000000 00000000 00000000 00000100 拷贝最前面一位0,抛弃向右移除的一位0,结果二进制如下 000000000 00000000 00000000 0000001 4 >>> 2 最终结果:1
    // 偶数 & 1 = 0
    // 奇数 & 1 = 1
    console.log(2 & 1)    // 0
    console.log(3 & 1)    // 1
    
    console.log(~~ 1.1)    // 6
    console.log(1.1 >> 0)  // 6
    console.log(1.1 << 0)  // 6
    console.log(1.1 | 0)   // 6
    // >>>不可对负数取整
    console.log(1.1 >>> 0)   // 6
    

    除以2向下取整

    console.log(4 >> 1);
    console.log(5 >> 1);
    
    let m = 1
    let n = 2
    m ^= n
    n ^= m
    m ^= n
    console.log(m)   // 2
    console.log(n)   // 1
    
    console.log(1 === 1 >>> 0)
    console.log(-1 === -1 >>> 0)
    复制代码
    分类:
    前端