位运算计算器,免费
对整数执行位运算,并以十进制、十六进制和二进制查看结果。
工作原理
- 输入两个数字:输入要运算的值 , 可以是十进制、二进制(前缀 0b)或十六进制(前缀 0x)。
- 选择运算:选择 AND、OR、XOR、NOT、左移(<<)或右移(>>)。
- 查看结果:输出会同时以十进制、二进制和十六进制显示结果,并附带按位可视化。
为什么使用位运算计算器?
位运算是系统编程、密码学、游戏开发、图形学、网络和嵌入式系统中的基础。理解 AND、OR、XOR 和移位如何操作各个比特位,对于开关标志位、紧凑存储数据和实现高效算法至关重要。这款计算器在比特层面展示运算过程,让您清楚看到每一位是如何被影响的。
功能特性
- 全部位运算符:AND(&)、OR(|)、XOR(^)、NOT(~)、左移(<<)和右移(>>)。
- 多进制输入:可以用十进制、二进制(0b…)或十六进制(0x…)输入数字。
- 多进制输出:结果同时以十进制、二进制和十六进制显示。
- 比特可视化:可视化网格显示每个操作数和结果中哪些位被置位。
- 有符号/无符号模式:可在 8、16、32 和 64 位整数之间切换。
常见问题
XOR 在编程中有什么用?
XOR(^)用于翻转位、进行简单加密/混淆、不用临时变量交换两个变量、奇偶校验和混合哈希值。当两个位不同时返回 1,相同时返回 0。
<< 和 >> 有什么区别?
左移(<<)将所有位向左移动,相当于乘以 2 的幂。右移(>>)将所有位向右移动,相当于除以 2 的幂。算术右移保留符号位;逻辑右移用 0 填充。
如何设置或清除某一位?
设置第 n 位:value |= (1 << n)。清除第 n 位:value &= ~(1 << n)。翻转第 n 位:value ^= (1 << n)。检查第 n 位是否被设置:(value & (1 << n)) !== 0。
从布尔代数到硅:位运算如何成为通用
每个现代CPU实现的位运算来自两篇相隔80多年发表的奠基性论文。1854年,George Boole发表了《An Investigation of the Laws of Thought》,定义了二值逻辑的代数,AND、OR、NOT及其恒等式。这是一项哲学工作,而不是工程工作。然后在1937年,一位21岁的麻省理工学院研究生Claude Shannon撰写了他的硕士论文《A Symbolic Analysis of Relay and Switching Circuits》,证明布尔代数可以描述电气继电器电路,因此任何逻辑计算都可以物理实现。这篇论文被广泛引用为20世纪最重要的硕士论文,是所有数字电子的基础。每个CPU使用的负数二进制表示二进制补码,于1962年由Burroughs Corporation取得专利,但已在IBM 704(1954)和其他早期机器中使用。IEEE 754在1985年标准化了浮点表示,固定了每个JavaScript Number仍在使用的位布局,binary64的1符号位、11指数、52尾数。今天,C语言运算符& | ^ ~ << >>几乎直接映射到单个CPU指令,这就是为什么位运算代码可以比算术等效项快得多的原因。
六个运算符,它们在位级别做什么
- AND(
&)仅当两个输入位都为1时,结果位才为1。0b1100 & 0b1010 = 0b1000。用于掩码、隔离特定位或检查标志是否设置:flags & FLAG_READ当且仅当FLAG_READ启用时为非零。 - OR(
|)如果任一输入位为1,结果位为1。0b1100 | 0b1010 = 0b1110。用于设置位、组合标志:flags = FLAG_READ | FLAG_WRITE。 - XOR(
^)如果恰好一个输入位为1,结果位为1。0b1100 ^ 0b1010 = 0b0110。用于切换位、简单混淆(x ^ x = 0,所以XOR是其自身的逆)、奇偶校验和哈希混合。 - NOT(
~)翻转每个位。~0b0000_1111 = 0b1111_0000(在8位中)。在二进制补码中,~x等于-x − 1,所以在JavaScript中~5 === -6。 - 左移(
<<)将所有位向左移动n个位置,右侧用零填充。1 << 3 === 8,相当于乘以2³。用于构建位掩码:1 << n是「位置n上的位」。 - 右移(
>>算术,>>>逻辑)向右移动位。算术移位(JS、Java、C有符号中的>>)保留符号位;逻辑移位(JS中的>>>,C无符号中的>>)用零填充。-8 >> 1 === -4但JavaScript中-8 >>> 1 === 2147483644因为>>>先强制转换为32位无符号整数。
位运算真正发挥作用之处
- 位标志和功能开关将32个布尔选项打包到一个整数中。Linux文件权限(
chmod 755)、网络协议头(TCP、IPv4)和OpenGL状态标志都使用这种模式。一次&检查告诉你功能是否启用。 - Unix文件权限
rwxr-xr-x是0b111_101_101 = 0o755 = 493。三组是用户/组/其他,每三位是读/写/执行。chmod计算器将符号形式转换为shell想要的整数。 - IP子网掩码
/24掩码是255.255.255.0或0xFFFFFF00。要检查IP是否在子网中:(ip & mask) === (network & mask)。被世界上每个路由器和防火墙使用。 - 密码学和哈希 SHA-256、AES、ChaCha20、BLAKE3,每种现代哈希和密码主要由AND、OR、XOR、NOT和旋转构建。XOR本身是一次性密码本的基础,当密钥真正随机且使用一次时,这些密码本被证明是不可破解的。
- 颜色操作 32位RGBA颜色打包四个8位通道:
(R << 24) | (G << 16) | (B << 8) | A。要提取红色通道:(color >> 24) & 0xFF。被HTML canvas、OpenGL和每种图像格式使用。 - 性能技巧在大多数CPU上
x & 1比x % 2快得多(一个周期vs ~10)。x >> 1在一个周期内除以2。二次幂对齐、位人口计数和位操作技巧在性能关键代码中无处不在。(参见Sean Anderson的「Bit Twiddling Hacks」页面,这是一个著名的目录。) - 嵌入式系统微控制器将硬件寄存器映射到内存中的特定位位置。配置UART或GPIO引脚需要掩码和移位以读取或写入正确的位而不干扰其余部分。C的位字段语法是这些模式的便利糖。
会咬人的错误
- 混淆
&与&&以及|与||单一形式是位运算,双重形式是短路逻辑。1 & 2 === 0(无共享位)但1 && 2 === 2(都是真值,返回第二个)。混淆它们会无声地破坏条件逻辑。 - 运算符优先级惊喜
x & FLAG === 0意味着x & (FLAG === 0),而不是(x & FLAG) === 0,因为===的绑定比&更紧密。始终在条件中给位运算表达式加括号。 - 有符号vs无符号移位混淆在JavaScript中,
>>是算术(符号扩展),>>>是逻辑(零填充)。C通过变量类型区分,有符号类型使用算术,无符号使用逻辑。Java像JavaScript一样同时有>>和>>>。不匹配语言约定会无声地翻转含义。 - JavaScript对位运算截断为32位尽管
Number是64位浮点数,所有位运算符首先将操作数强制转换为int32。0x100000000 & 0xFF === 0,不是0+低字节,因为操作数在AND之前被截断为32位。对于64位位操作,使用BigInt,它有自己的位运算符。 - 在JavaScript中移位> 31
1 << 32 === 1,不是0。移位量被取模32。C更危险:移位超过位宽是未定义行为,所以编译器可以做任何事。在按运行时值移位之前,始终检查n < bitWidth。 - 字节打包代码中的字节序
(r << 24) | (g << 16) | (b << 8) | a产生0xRRGGBBAA。字节是按该顺序存储还是在内存中反转,取决于平台。HTML canvas中的ImageData在x86上是小端;PNG文件格式是大端。读取二进制格式时,使用DataView显式转换。 - 忘记二进制补码
~0 === -1,不是0xFFFFFFFF,因为全1是−1的二进制补码编码。要在JavaScript中获取无符号32位解释:(~0) >>> 0 === 4294967295。
为什么使用二进制补码,以及它在位级别意味着什么
每个现代CPU使用二进制补码表示负整数。在一个有符号8位字节中,0到127的值被编码为二进制0000_0000到0111_1111。然后−1被编码为1111_1111,−2为1111_1110,直到−128为1000_0000。原因:使用此编码,无论输入是有符号还是无符号,加法都以相同的方式工作,CPU不需要单独的add-signed和add-unsigned指令。不对称的是,负范围比正范围大一(在8位中,−128到+127),这就是为什么在每种具有固定宽度整数的语言中Math.abs(INT_MIN)溢出。早期的符号-数值(一位用于符号,其余用于大小)和一进制补码编码存在于1950-60年代,但输给了二进制补码,因为它们有零的两种表示形式,并且需要特殊情况硬件进行取反。
更多常见问题
为什么~5等于-6而不是250?
因为在二进制补码(每个现代CPU使用的编码)中,翻转正数的每个位得到-n - 1。所以~5 === -6和~0 === -1。在无符号8位上下文中,与~5相同的位模式(二进制1111_1010)将代表250。JavaScript将结果视为有符号32位,所以你看到-6。要获取无符号解释:32位中的(~5) >>> 0,得到4294967290,或者用~5 & 0xFF掩码到8位得到250。
XOR真的是一种加密吗?
XOR是每种现代对称密码的构建块,但单独的XOR不是安全加密。一次性密码本,XOR与一个真正随机的、与消息一样长、恰好使用一次的密钥,在信息论上是不可破解的(Shannon,1949)。重用密钥,或使用比消息短的密钥,频率分析会轻易破解它。像AES这样的真正密码使用XOR加扩散和替换,将短密钥放大为一串伪随机字节,在没有密钥的人看来像一次性密码本。所以「用XOR加密」仅适用于琐碎的混淆,绝不适用于真正的秘密。
什么时候我应该使用BigInt而不是Number进行位操作?
任何时候你需要超过32位的位级精度。JavaScript位运算符在计算之前将Number操作数截断为32位有符号整数。如果你需要64位掩码(例如,操作64位功能标志集、使用Linux mmap偏移量或实现SHA-512),使用BigInt:0xFFFFFFFFFFFFFFFFn & 0xFFn === 255n。BigInt比Number慢,根据操作约3-10倍,所以将其保留给32位真正不够的情况。
如何计算一个数中1位的数量?
这是人口计数或汉明权重。大多数现代CPU有单个指令(x86上的POPCNT,ARM上的VCNT)。在JavaScript中,没有内置,所以使用位操作经典:let c = 0; while (x) { c += x & 1; x >>>= 1; }。或来自Hacker's Delight的并行SWAR技巧:x = x - ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0F0F0F0F; return (x * 0x01010101) >>> 24;,大约十几个周期就能计算32位整数中的位数。
当我使用这个计算器时,我的数据会被发送到任何地方吗?
不。每个操作都在浏览器的JavaScript引擎中运行,计算期间不会发生网络调用。在DevTools中打开网络选项卡并单击计算,你将看到零出站请求。对敏感掩码、密钥或专有位布局工作安全。