使用方法
- 在「操作数 A」填第一个数。示例填
0b1100,即十进制 12;也可以直接填12或0xC,三种写法本页都认。 - 在「运算」下拉里选一种。示例选「加法 +」。
- 在「操作数 B」填第二个数。示例填
0b1010,即十进制 10。选「按位取反 NOT」时这一栏被忽略。 - 只有选「左移」或「右移」时才需要动「移位位数 k」,允许
0到256;其余运算下 k 这一栏不参与。 - 点「计算」或按 Enter,二进制计算器的结果区同时给出二进制、十进制、8 位补码和 32 位补码四栏。
这个二进制计算器能解决什么问题
掩码、寄存器、校验和、位图这些活儿都在二进制上做,手算竖式太慢也容易错。本页由二进制计算器处理四类具体问题:一是位掩码合并,12 | 10 得到 0b1110(14),用一条指令把两个标志位置起来;二是判断某一位是否被置起,12 & 10 得到 0b1000(8),说明只有第 3 位同时为 1;三是取反求掩码,~12 不是 3 也不是 12,而是十进制 -13,它的 8 位补码是 11110011;四是移位做除法近似,12 >> 1 得 0b110(6),等价于整除 2。
本页只做「两个数之间的运算」。只把二进制换成十进制、或反过来,不带任何运算的,请用文末的进制转换页;本页刻意不做那件事,避免和它们抢同一个搜索意图。
原理和变量:用 BigInt 而不是 Number
本页所有运算都把输入交给 BigInt() 解析,然后直接用 + - * / % & | ^ ~ << >> 这些运算符。关键在于为什么不用 Number 加 parseInt。
JavaScript 的 Number 是 IEEE 754 双精度浮点,尾数只有 53 位有效位,Number.MAX_SAFE_INTEGER 恰好是 253-1 = 9007199254740991。更糟的是位运算:ECMA-262 规定位运算符会先把左操作数走一遍 ToInt32,也就是先截断成 32 位有符号整数再运算。实测 1e10 | 0 的结果是 1410065408,而正确的 BigInt(1e10) >> 1n 是 5000000000——用 Number 算,答案从 50 亿变成 14 亿。掩码运算里出现这种错误不会报错,只会悄悄给你一个错的位模式。
BigInt 是任意精度整数,BigInt('0b1100') 直接得到 12n,位运算不做 32 位截断,因此不存在上面那个坑。ES2020 把它纳入标准,typeof 12n === 'bigint',可以和 Number 混算但不能混做位运算。
解析时为什么必须处理前缀。BigInt(str) 会按字面量前缀判断进制:带 0b 是二进制,带 0x 是十六进制,0o 是八进制,什么都不带就是十进制。所以 BigInt('1010') 得到 1010n(一千零一十),而 BigInt('0b1010') 才得到 10n。这是本页在 readNum() 里显式判断前缀、再决定是否补 0b 的原因。
补码视图怎么算。把结果 R 与上掩码 2w-1 做位与,R & (2w-1),得到的就是该宽度下的位串,左侧补零到 w 位。这一步对负数同样成立:-1 & 255 得 11111111,正是 -1 的 8 位补码。补码遵循 IEEE 754 之外的通行约定——最高位为 1 时表示负数,取反加一即得绝对值。
两个取不到值的运算符。其一,BigInt 没有无符号右移:写 1n >>> 1n 会抛 TypeError: BigInts have no unsigned right shift, use >> instead,这是规范里的显式禁止,不是本页的限制。其二,除数为 0 会抛 RangeError: Division by zero,本页提前拦下并给中文文案。
完整示例(数值仅作演示)
打开页面时 A 填 0b1100(12)、B 填 0b1010(10)、运算选加法,二进制计算器给出的六栏是:
- 结果二进制
10110,十进制22(手验:1100 + 1010从低位起0+0=0、0+1=1、1+0=1、1+1写 0 进 1,得10110= 22); - 8 位补码
00010110,32 位补码00000000000000000000000000010110; - 运算式
0b1100 + 0b1010 = 0b10110,位宽 5 位。
只改「运算」,A、B 不动,得到的是这一组数在二进制下的全部关系:
- 加法
1100 + 1010 = 10110(22)、减法1100 − 1010 = 10(2)、乘法1100 × 1010 = 1111000(120); - 整除
1100 ÷ 1010 = 1,余数10(2); - 位与
1100 & 1010 = 1000(8)、位或1100 | 1010 = 1110(14)、位异或1100 ^ 1010 = 110(6); - 取反
~1100 = -1101(-13),8 位补码11110011; - 左移一位
1100 << 1 = 11000(24)、右移一位1100 >> 1 = 110(6)。
换成 A 填 0b11111111(255)、B 填 0b1(1)做加法,结果是 0b100000000(256),但 8 位补码栏显示 00000000——这就是 8 位溢出,看补码栏能立刻发现。
输入范围与对照表
三种前缀的对照,同一个十进制 12 的不同写法:
| 写法 | 字面量 | 解析结果 | 说明 |
|---|---|---|---|
| 二进制 | 0b1100 | 12 | 必须带 0b,否则按十进制 |
| 十进制 | 12 | 12 | 无前缀即十进制 |
| 十六进制 | 0xC | 12 | 掩码配置里最常用的写法 |
| 八进制 | 0o14 | 12 | 文件权限位常用 |
4 位位模式全表(前 12 行默认显示,点「加载更多位模式」展开余下 4 行),这一段是掩码配置和十六进制对照片面的基础:
| 十进制 | 4 位二进制 | 0b 字面量 | 十六进制 | 8 位补码 |
|---|---|---|---|---|
| 0 | 0000 | 0b0000 | 0x0 | 00000000 |
| 1 | 0001 | 0b0001 | 0x1 | 00000001 |
| 2 | 0010 | 0b0010 | 0x2 | 00000010 |
| 3 | 0011 | 0b0011 | 0x3 | 00000011 |
| 4 | 0100 | 0b0100 | 0x4 | 00000100 |
| 5 | 0101 | 0b0101 | 0x5 | 00000101 |
| 6 | 0110 | 0b0110 | 0x6 | 00000110 |
| 7 | 0111 | 0b0111 | 0x7 | 00000111 |
| 8 | 1000 | 0b1000 | 0x8 | 00001000 |
| 9 | 1001 | 0b1001 | 0x9 | 00001001 |
| 10 | 1010 | 0b1010 | 0xA | 00001010 |
| 11 | 1011 | 0b1011 | 0xB | 00001011 |
| 12 | 1100 | 0b1100 | 0xC | 00001100 |
| 13 | 1101 | 0b1101 | 0xD | 00001101 |
| 14 | 1110 | 0b1110 | 0xE | 00001110 |
| 15 | 1111 | 0b1111 | 0xF | 00001111 |
常用位宽的上限值,掩码写 0xFF 还是 0xFFFF 取决于这里:
| 位宽 | 最大值(十进制) | 全 1 的十六进制 | 说明 |
|---|---|---|---|
| 4 位 | 15 | 0xF | 一个半字节,十六进制一位 |
| 8 位 | 255 | 0xFF | 一个字节 |
| 16 位 | 65535 | 0xFFFF | 字符编码的常用宽度 |
| 31 位 | 2147483647 | 0x7FFFFFFF | 231-1,有符号 32 位的正数天花板 |
| 32 位 | 4294967295 | 0xFFFFFFFF | 232-1,IPv4 地址上限 |
| 64 位 | 18446744073709551615 | 0xFFFFFFFFFFFFFFFF | 264-1,超出 Number 安全整数 |
边界与精度
操作数上限 40 个字符。输入框的 maxlength 是 40,按最坏情况(二进制 40 位)结果约 1012;即使做乘法也只有 80 位,BigInt 轻松处理。移位位数单独限制在 0 到 256,因为 1n << 100000n 会生成 100001 位的数字串,直接塞进页面会把排版撑坏。
精度结论。本页不存在精度丢失问题。253+1 = 9007199254740993 用 Number 算会等于 253(253+1 === 253 为 true),用 BigInt 算就是精确的 9007199254740993。这就是本页坚持 BigInt 的唯一理由。
每条非法路径都有对应文案。空输入报「操作数 A 还没有内容」;含 2 到 9 的二进制串报出第一个非法字符的位置;带 e 或小数点报不支持科学计数法;纯除法时 B 为 0 报「除数不能为 0」;0b 后面没有数字报格式错误。全部指明字段和允许范围,不做静默归零。
整除的语义要记住。/ 在 BigInt 上是向零取整而不是向下取整,所以 -7n / 2n 得 -3n(不是 -4)。想要数学上的向下取整,得自己用 q - (a % b !== 0n ? 1n : 0n) 修正,本页的「整除」栏给的是向零结果,同时单列「取余 %」让你自己核对。
常见问题
为什么不能直接用 Number 做位运算?
因为 ECMAScript 规定位运算符先把操作数走 ToInt32,也就是截断成 32 位有符号整数。实测 1e10 | 0 得 1410065408,而 BigInt(1e10) >> 1n 得 5000000000。这种错误不抛异常,只是悄悄返回错误的位模式,掩码和校验和场景下极难察觉。
取反 ~12 为什么是 -13 而不是 3?
按位取反是对补码逐位翻转,结果按有符号数解释。12 的二进制是 1100,逐位翻转得 0011,但 BigInt 认为它是无限位补码下的 ...11111011,即十进制 -13。通式是 ~A = -A - 1,所以 ~12 = -13。要看它的位串请看 8 位补码栏 11110011。
为什么 1n >>> 1n 会报 TypeError?
规范明确禁止对 BigInt 使用无符号右移,因为 BigInt 没有固定位宽,「无符号」这个概念无从定义。想做纯逻辑右移,先转成 32 位视图:Number(x & 0xFFFFFFFFn) >>> n。直接写 >>> 属于规范层面的错误,不是本页的限制。
8 位补码显示 00000000,是不是算错了?
不是,这是 8 位溢出。255 + 1 = 256 的真实值是 0b100000000(9 位),塞进 8 位窗口时最高位被丢掉,剩下全 0。判断溢出要看「结果位宽」那一栏:它显示 9 就说明 8 位窗口装不下。
12 ÷ 10 的结果是 1,为什么不给 1.1?
因为 BigInt 只有整数,/ 必然整除,向零取整得 1n,余数在「取余 %」里给出。想得到小数,用十进制输入 12.0 也不行——BigInt('12.0') 会直接抛 SyntaxError。本页的定位是整数与位运算,不做二进制浮点。
输入 1010 为什么变成了 1010 而不是 10?
因为没有 0b 前缀。BigInt() 按字面量规则判断进制:无前缀是十进制,0b 是二进制,0x 是十六进制,0o 是八进制。1010 因此被读成一千零一十。想表示十号请写 0b1010,这也是本页对超过 9 的纯数字串会提示「疑似漏写 0b 前缀」的原因。
264-1 用 JavaScript 打印为什么变成 18446744073709552000?
那是因为先被 Number 接住了,尾数 53 位不够放下 20 位十进制数,末尾被四舍五入。本页内部全程用 BigInt,对照表里的 18446744073709551615 是精确值;你若在控制台用普通数字复算,看到的截断值不代表本页算错。
输入的操作数会被保存或上传吗?
不会。三个输入框的值只交给本页 IIFE 里的 BigInt() 解析,全页没有 fetch、没有 XMLHttpRequest,可在开发者工具 Network 面板自查。刷新后即恢复默认的 0b1100 与 0b1010。
相关工具
- 十进制转二进制转换器:只做进制换算,不带运算,输出带分组位串。
- 二进制转十进制转换器:反向换算,位串超长时按 4 位分组显示。
- 数字进制转换器:二、八、十、十六进制四者互转的通用入口。
- 十六进制计算器:同一套位运算,但默认口径是十六进制,适合看寄存器与内存地址。
- 文本转二进制:把字符串按 UTF-8 字节展开成 0/1 串,不做算术。
- 二进制转文本:把 0/1 串按字节还原成可读字符串。
- ASCII表格生成器:0~127 的十进制、八进制、十六进制与字符对照表。