位运算计算器处理的,是机器真正存储的 32 位字,而不是你输入的十进制数。位运算计算器取两个数,套用 7 种运算之一(按位与、按位或、按位异或、非 A、非 B、左移、右移),一次性把结果打印成 5 种进制:十进制、十六进制、8 位二进制、32 位二进制与八进制。不上传;运算全部在浏览器的 JavaScript 整数上进行。本文用具体数字走完每一种运算,展示符号位如何钻进移位,以及让按位与成为字节级代码主力军的掩码。
一个 32 位字上的 7 种运算
3 种两元运算逐位作用。12 是 0b1100,10 是 0b1010:按位与只保留两个数都是 1 的位,所以 12 与 10 = 0b1000 = 8;按位或保留至少一个是 1 的位,12 或 10 = 0b1110 = 14;按位异或保留恰好一个是 1 的位,12 异或 10 = 0b0110 = 6。两个取反按钮把操作数的每一位翻转:5 是 0b0101,翻转后的 0b1010 是 -6 的二补读法,32 位十六进制里打印为 0xFFFFFFFA。两个移位把位移动:1 左移 4 位是 16,1024 右移 2 位是 256。想不碰位、只把同一个数换进制,进制转换器做纯进制换算。
三种输入进制,同一个 32 位值
每个输入框接受纯十进制、0x 前缀的十六进制与 0b 前缀的二进制,解析器在三种写法背后保留同一个 32 位整数。0xFF 与 0x0F 得 15,是每条字节协议里都会见到的低 4 位掩码。输入时,工具把每个操作数回显为按 4 位分组的 32 位二进制串;结果面板把最低 8 位画成 8 个亮灭方块:255 全亮,16 只亮 1 个。用眼睛读这些分组,和把文字转成二进制码是同一项技能,文本二进制转换逐字母练它。
移位、符号位与 31 掩码
右移是算术右移:移动时复制符号位,所以 -8 是 0xFFFFFFF8,-8 右移 1 位得 0xFFFFFFFC = -4,而不是 0x7FFFFFFC。左移从右边补 0,但第 31 位是 32 位字的符号位,所以 1 左移 30 位 = 1073741824(0x40000000)仍是正数,而 1 左移 31 位 = -2147483648,是最小的负数。移位量先被掩码到 0 到 31 之间:1 左移 33 位与 1 左移 1 位完全一样,返回 2。没有报错,没有溢出提示。从字里抽出一个字节是日常模式:0xFF00 右移 8 位得 255。做字节级的十六进制与 UTF-8 互转,Hex UTF-8 Base64 转换器是同一视图的兄弟。
一次看 5 种进制
结果面板把同一个值打 5 种写法:十进制、十六进制(大写,0x 前缀)、8 位二进制、32 位二进制与八进制。255 打印为 255、0xFF、0b1111 1111、32 位视图里前 24 位全 0 的串,以及 0o377。八进制那一列不是装饰:文件权限三位数是八进制,因为每个八进制位恰好是一组 3 个权限位,所以 0o755 是 9 位的 0b111101101,即 rwxr-xr-x,十进制是 493。Chmod 权限计算器把这个三位数展开成属主、属组与其他人的 3 行,正是这一列的位级视图。
掩码:按位与的日常工作
和一个小数做按位与,只保留低位:0xFF 与 0x0F 得 15,-1 与 7 得 7,因为 -1 是全 1。测试单个标志位就是 值 与 (1 左移 n):结果非零,说明第 n 位是 1。按位异或是自己的逆运算,所以是一行密码:65 异或 42 = 107,107 异或 42 = 65,同一个密钥异或两次,字节原样回来。15 在三种紧凑进制里是 0b1111、0o17 与 0xF。把字节打包成文字的编码,比如 Base64,就坐在这节的 6 位分组上,Base64 编解码器展示那张映射表。
同样的 0 和 1,处处都在
位运算是所有按字节计算的东西底下的一小层。文本二进制转换指南把字符手工拆成 8 位分组;哈希生成器再用恰好这些运算——按位与、或、异或和轮换——把整个缓冲区混到 32 位摘要出来。当问题是想用哪种进制读一个值,从位开始:本站的每种进制,从这里的 8 位方块到八进制权限位,都是同一个 32 位字穿着不同记法。计算器让这个字不再抽象:两个输入,一种运算,五种读法。