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

一、位移运算

位移运算(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指令集的编程。而位运算也可以这样去类比。对于计算机的底层而言都是由二进制组成,二进制的计算更偏向底层计算。

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

相关推荐
宁檬精2 小时前
算法练习——55.跳跃游戏
数据结构·算法·游戏
王璐WL2 小时前
【C语言入门级教学】内存函数
c语言·开发语言·算法
啃啃大瓜2 小时前
python常量变量运算符
开发语言·python·算法
恋猫de小郭2 小时前
Flutter Riverpod 3.0 发布,大规模重构下的全新状态管理框架
android·前端·flutter
wordbaby2 小时前
用 window.matchMedia 实现高级响应式开发:API 全面解析与实战技巧
前端·javascript
薄雾晚晴2 小时前
Rspack 实战,构建流程升级:自动版本管理 + 命令行美化 + dist 压缩,一键输出生产包
前端·javascript
熊文豪3 小时前
【华为OD】找出通过车辆最多颜色
算法·华为od
huabuyu3 小时前
在 Taro 小程序中实现完整 Markdown 渲染器的实践
前端
晚星star3 小时前
在 Web 前端实现流式 TTS 播放
前端·vue.js