位运算左移右移应该怎么玩?

一、位移运算

位移运算(Bit Shift Operation)是计算机科学中最基础的位操作之一,它直接对二进制数的位模式进行操作。所有现代编程语言都支持位移运算,包括JavaScript、Java、C/C++等。位移运算分为左移(<<)和右移(>>、>>>)两种主要类型,每种类型在底层处理上有显著差异。

1.1 二进制表示

计算机中整数通常以32位二进制补码形式存储。例如十进制数18的二进制表示为00000000000000000000000000010010,而负数如-18则通过补码表示:先取绝对值的二进制,取反后加1,得到11111111111111111111111111101110

二、左移(<<)

2.1 运算规则

左移运算符将操作数的所有二进制位向左移动指定位数,右侧空位补0,左侧超出的位被丢弃。数学上,左移n位等价于乘以2的n次方(仅当没有有效位被移出时成立)。

示例1‌:

bash 复制代码
8 << 2 的计算过程:
8的二进制:00001000
左移2位:  00100000(十进制32)

结果为32,因为8×2²=32

示例2‌:

bash 复制代码
-3 << 3 的计算过程:
-3的补码:11111111111111111111111111111101
左移3位: 11111111111111111111111111101000(十进制-24)

结果为-24,因为-3×2³=-24

2.2 底层硬件实现

左移操作在CPU指令集中通常对应SHL(Shift Left)指令,其执行只需1个时钟周期,比乘法指令快5-10倍(基本上是纳秒,但是呢如果不是密集运算其实对用户没有感知)。

三、右移

3.1 算术右移(>>)

保留符号位的右移,正数左侧补0,负数左侧补1。

示例1‌:

复制代码
12 >> 2 的计算过程:
12的二进制:00001100
右移2位:   00000011(十进制3)

结果为3,因为12÷2²=3

示例2‌:

diff 复制代码
-8 >> 2 的计算过程:
-8的补码:11111111111111111111111111111000
右移2位: 11111111111111111111111111111110(十进制-2)

结果为-2,保持符号不变

3.2 逻辑右移(>>>)

无符号右移,左侧始终补0,适用于处理无符号数或位掩码。

示例‌:

diff 复制代码
-8 >>> 2 的计算过程:
-8的补码:11111111111111111111111111111000
逻辑右移2位:00111111111111111111111111111110(十进制1073741822)

结果变为正数1073741822

四、位移运算的底层细节

4.1 位数限制

在JavaScript中,位移运算前操作数会被转换为32位整数,超过32位的部分被截断。例如:

bash 复制代码
(0x123456789 << 1).toString(16) 
// 实际计算的是0x23456789 << 1 = 0x468ACF12

4.2 补码运算机制

负数的右移涉及补码的特殊处理:

  1. 算术右移保持符号位扩展
  2. 逻辑右移忽略符号位

五、意外情况

  1. 移位数限制‌:多数语言限制移位数必须小于数据类型位数(如JS中移位数取模32)
  2. 溢出风险 ‌:左移可能导致符号位改变,如0x40000000 << 1结果为负数

六、实际开发怎么用?

6.1 优化场景

左移运算(<<)常被用于替代乘法运算以提高性能,特别是在需要频繁进行2的幂次方计算的场景中。例如在游戏循环或动画渲染中:

arduino 复制代码
// 传统乘法
const scale = size * 8;

// 优化后的位运算
const scale = size << 3;  // 等效于乘以8

右移运算(>>)则可用于替代除法运算,特别适合处理整数运算的场景:

ini 复制代码
// 传统除法
const half = value / 2;

// 优化后的位运算
const half = value >> 1;  // 等效于除以2并取整

6.2 颜色值处理

在Canvas和WebGL编程中,左移运算常用于将RGB颜色分量打包成单个32位整数:

scss 复制代码
function rgbToInt(r, g, b) {
    return (r << 16) | (g << 8) | b;
}

// 使用示例
const red = 255, green = 128, blue = 64;
const color = rgbToInt(red, green, blue);  // 0xFF8040

反向操作则使用右移运算提取颜色分量:

javascript 复制代码
function intToRgb(color) {
    return {
        r: (color >> 16) & 0xFF,
        g: (color >> 8) & 0xFF,
        b: color & 0xFF
    };
}

6.3 权限控制系统

左移运算可用于定义权限标志位,右移运算用于检查权限:

javascript 复制代码
// 定义权限常量
const READ = 1 << 0;    // 0001
const WRITE = 1 << 1;   // 0010
const EXECUTE = 1 << 2; // 0100

// 组合权限
let userPermissions = READ | WRITE;  // 0011

// 检查权限
function hasPermission(permissions, permission) {
    return (permissions & permission) === permission;
}

// 使用示例
console.log(hasPermission(userPermissions, READ));  // true
console.log(hasPermission(userPermissions, EXECUTE)); // false

6.4 数据压缩与存储

左移运算可用于将多个小数值打包到单个整数中存储:

scss 复制代码
// 将4个4位数值(0-15)打包成16位整数
function packValues(a, b, c, d) {
    return (a << 12) | (b << 8) | (c << 4) | d;
}

// 解包
function unpackValues(packed) {
    return [        (packed >> 12) & 0xF,        (packed >> 8) & 0xF,        (packed >> 4) & 0xF,        packed & 0xF    ];
}

6.5 特殊算法实现

6.5.1 快速幂运算

利用左移运算实现快速幂计算:

csharp 复制代码
function fastPower(base, exponent) {
    let result = 1;
    while (exponent > 0) {
        if (exponent & 1) {
            result *= base;
        }
        base *= base;
        exponent >>= 1;
    }
    return result;
}

七、唠叨

以上这些应用场景展示了位运算在开发中的强大能力,特别是在需要高性能计算或底层数据处理的场合,但是从宏观方面来分析,不管是左移还是右移,从上面得出来的规律都知道,如果不使用左移和右移,他们的计算步骤要被拆分为几步,而一个运算就是CPU的一个指令执行周期就如上文提到的一个时钟周期一样,而左移和右移只需要移动N个二进制,这样就会比直接使用左移和右移多几个指令执行周期,可能运算比较少的时候,差异不大。但是大规模运算中使用位运算的优势就出现了。大家应该都明白,系统开发和硬件开发都是使用C和汇编进行开发,他们的效率高在哪里了?少了很多高级的封装,减少了编译的次数,基本是面向CPU指令集的编程。而位运算也可以这样去类比。对于计算机的底层而言都是由二进制组成,二进制的计算更偏向底层计算。

权衡:虽然位运算性能高,但会降低代码可读性(具体取决于你所在的团队),这是一个权衡过程。

相关推荐
小陈工1 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
海清河晏1111 小时前
数据结构 | 单循环链表
数据结构·算法·链表
wuweijianlove5 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
_dindong5 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志5 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
xiaotao1315 小时前
第九章:Vite API 参考手册
前端·vite·前端打包
午安~婉5 小时前
Electron桌面应用聊天(续)
前端·javascript·electron
黎阳之光6 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_116 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia6 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode