Skip to content

原码/反码/补码/移码计算器 — 四种码一次算全

在线原码/反码/补码计算器,一次算出原码、反码、补码与移码四种表示,支持 4/8/16/32/64 位。也可反过来粘贴 11111011 或 0xFB,看它按无符号、原码、反码、补码、移码分别读作多少。-128 在 8 位下没有原码和反码,本工具会明确标出并解释为什么。全程浏览器本地计算。

无追踪 浏览器中运行 免费
全部计算都在你的浏览器本地完成——你输入的内容不会离开这台设备。
位宽

十进制转机器表示

输入一个有符号整数。四种表示会同时算出来——你不必事先知道自己的系统用的是哪一种。

试试这些
编码 位串 十六进制
原码 1000 0101 85
反码 1111 1010 FA
补码 1111 1011 FB
移码 0111 1011 7B

位串转数值

你在内存 dump 或寄存器里看到一个字节,却不知道它该怎么读。粘进来,同一串位在每一种解释下的含义会一次全部列出——哪一种才对取决于产生它的系统,所以这里全都给你。

读作 数值
无符号 251
原码 -123
反码 -4
补码 -5
移码 123
8 位对照表

由上方工具所用的同一份引擎算出,所以两者不可能对不上。

十进制 原码 反码 补码 移码 十六进制
127 0111 1111 0111 1111 0111 1111 1111 1111 7F
100 0110 0100 0110 0100 0110 0100 1110 0100 64
10 0000 1010 0000 1010 0000 1010 1000 1010 0A
5 0000 0101 0000 0101 0000 0101 1000 0101 05
1 0000 0001 0000 0001 0000 0001 1000 0001 01
0 0000 0000 0000 0000 0000 0000 1000 0000 00
-1 1000 0001 1111 1110 1111 1111 0111 1111 FF
-5 1000 0101 1111 1010 1111 1011 0111 1011 FB
-10 1000 1010 1111 0101 1111 0110 0111 0110 F6
-100 1110 0100 1001 1011 1001 1100 0001 1100 9C
-127 1111 1111 1000 0000 1000 0001 0000 0001 81
-128 1000 0000 0000 0000 80
各位宽的取值范围
位宽 补码 / 移码 原码 / 反码
4 -8 … 7 -7 … 7
8 -128 … 127 -127 … 127
16 -32768 … 32767 -32767 … 32767
32 -2147483648 … 2147483647 -2147483647 … 2147483647
64 -9223372036854775808 … 9223372036854775807 -9223372036854775807 … 9223372036854775807
五种位宽下的每一种编码都在测试套件里做了断言,包括 4 位的全部取值、零的两个位型,以及每个位宽下最负的那个值。64 位结果另以 JavaScript 自带的 BigInt.asIntN 与 BigInt.asUintN 作独立参照交叉校验。 — Go Tools 团队 · 2026年9月9日

由 Go Tools 工程团队构建并验证。

补码速查答案

-5 的 8 位补码是多少?

11111011 11111011,十六进制 0xFB。

一个有符号字节的范围是多少?

-128 … 127 补码是 -128 到 127;原码和反码都是 -127 到 127。

怎么把补码位型还原成数?

无符号值 − 2^n 最高位是 0 就按无符号读;是 1 就用无符号读数减去 2^n。

0xFF 是 -1 还是 255?

-1 或 255 按有符号字节是 -1,按无符号字节是 255。光看位定不了。

什么是补码?

补码回答的是一个硬件问题而不是数学问题:怎样存负数,才能让已经造好的加法器继续用?办法是用 2^n - x 的位型来表示 -x。这样加法在模 2^n 意义下自动回绕并落到正确结果上,符号不需要任何特例,减法也就不必再单独造一套电路。

由此引出两个后果,两个都会在真实的 bug 里出现。第一,范围是不对称的:8 位覆盖 -128 到 127 而不是 -128 到 128,因为位型总量要分配,而补码没有负零去把两边凑齐。第二,符号不是一个可以单独摘掉的标志位——11111011 的最高位是 1,但它的值是 -5 而不是 -123,读一个负数必须解释整个字,只看一位是不够的。

原码和反码是竞争中落败的两种设计。它们仍然值得了解,一是因为 IEEE 754 浮点数保留了原码式的布局,二是因为只有摆在一起对照,补码才显得是必然而不是随意的选择。

// -5 as an 8-bit byte, three ways to arrive at the same pattern
0b00000101        // 5
~0b00000101       // 11111010  ones' complement of 5
~0b00000101 + 1   // 11111011  two's complement = -5

// In JavaScript the width matters: bitwise operators are 32-bit,
// so anything wider has to go through BigInt.
BigInt.asIntN(8, 0xFBn)                 // -5n
BigInt.asUintN(8, -5n)                  // 251n
BigInt.asIntN(64, 0xFFFFFFFFFFFFFFFBn)  // -5n

// C23 made two's complement mandatory for signed integers.
// Before that, the other two encodings were legal but unused.

本计算器能做什么

四种编码一次给全

原码、反码、补码、移码同时算出。移码是多数计算器不做的那一个,而它恰好是 ADC 数据手册一直在用的那一个。

支持从位串反查

把你手上真正拿到的位串或十六进制粘进去,五种读法(含无符号)一并列出。dump 和设备报的数对不上时,需要的正是这个方向。

64 位是对的

所有数值都用 BigInt 处理,所以 0xFFFFFFFFFFFFFF9C 得到的是 -100,而不是 32 位截断之后的某个数。

没有表示就说没有表示

位宽 8 下的 -128 既没有原码也没有反码。表格会如实写明,而不是印一个并不表示这个数的位型。

把负零显示出来

输入 0,页面会给出零在原码和反码里的第二个位型——这是「补码为什么赢」最直观的一条证据。

不跑 JS 也能看的对照表

8 位对照表和各位宽的取值范围是构建时渲染的,用的是驱动上面输入框的同一份引擎,所以两者不可能对不上。

还有哪些办法可以核对有符号值

语言自带的转换函数

运行时 API

BigInt.asIntN、Python 的 int.from_bytes(..., signed=True)、C 的定宽类型,对你正在写的代码给出的是权威答案。代码里用它们;手上有个值而又没开解释器的时候用本页。

调试器的内存视图

IDE 功能

它按程序声明的类型显示数值,而类型恰好是一串裸位所缺的那条信息。当字节是从线上收来、根本没有声明类型时它就帮不上忙——那正是本页要处理的情况。

进制转换器

本站工具

它在各进制之间转换,但只处理非负数——负数在那里是被明确拒绝的,因为「进制」本身对符号怎么存没有主张。有符号表示归本页管,绝对值的进制转换归它管。

IEEE 754 转换器

本站工具

浮点数那一侧的对应工具。它用的是原码式布局而不是补码,指数还带 2^(e-1)-1 的偏移,所以两个页面回答的是关于同一个内存字的两个不同问题。

原码反码补码计算实例

-5 存进一个字节

-5,位宽 8
原码  1000 0101
反码  1111 1010
补码  1111 1011  (0xFB)
移码  0111 1011

三种编码只在符号位上一致,其余全都不同。真正装进 C 的 int8_t 里的,只有补码那一行。

同一个字节 0xFB 的五种读法

0xFB,位宽 8
无符号  251
原码   -123
反码   -4
补码   -5
移码   123

-128 没有原码

-128,位宽 8
原码  该位宽下没有表示
反码  该位宽下没有表示
补码  1000 0000  (0x80)
移码  0000 0000

原码和反码各拿一个位型去表示负零,所以范围是 -127 到 127,够不到 -128。在这里给出一个位型的工具是错的。

一个 64 位寄存器值

0xFFFFFFFFFFFFFF9C,位宽 64
补码    -100
无符号  18446744073709551516

超过 32 位就必须用 BigInt。JavaScript 的 |<<>>> 会静默截断到 32 位,这正是有些在线计算器在这里给出错误答案而不是报错的原因。

补码计算器怎么用

  1. 1

    先选位宽

    4、8、16、32 或 64。这不是显示偏好——同一串位在不同位宽下代表不同的数,选错了答案就变了。

  2. 2

    输入有符号十进制

    输入一个整数,负号照写。四种编码随输入实时更新,每种同时给出十六进制形式。

  3. 3

    或者从位串反推

    把二进制串或 0x 开头的十六进制粘进反查框,就能看到这串位在每一种解释下代表什么,包括无符号读法。

  4. 4

    留意出现的提示

    页面会标出最容易翻车的两处:最负的那个值在原码和反码下没有表示,以及零在这两种编码里有第二个位型。

会算出错误答案的几种做法

忘了加 1

逐位取反得到的是反码。停在这一步就与补码差了 1,而且很难发现,因为结果看上去仍像一个合理的负数。

✗ 错误
5   = 00000101
~5  = 11111010   <- ones' complement, not -5
✓ 正确
5        = 00000101
~5       = 11111010
~5 + 1   = 11111011   <- -5 in two's complement

在 64 位值上用 32 位的位运算符

JavaScript 会把位运算符的操作数截断到 32 位。高一半悄悄消失且不报错,所以结果是错的而不是缺失的。

✗ 错误
0xFFFFFFFFFFFFFFFB        // 18446744073709552000  -- the literal is already rounded
~0xFFFFFFFFFFFFFFFB + 1   // 0  -- silently wrong, expected -5
✓ 正确
BigInt.asIntN(64, 0xFFFFFFFFFFFFFFFBn)   // -5n

把负数做零扩展

补零扩宽只有在数是正的时候才保值。负数必须把符号位复制到新增的那些位上。

✗ 错误
int8  0xFB  (-5)
int16 0x00FB  (251)   <- zero-extended
✓ 正确
int8  0xFB  (-5)
int16 0xFFFB  (-5)    <- sign-extended

给最负的值编一个原码

8 位下的 -128 既没有原码也没有反码,因为这两种编码各花掉一个位型去表示负零。给它印上 10000000,是把补码的答案套在一种根本表达不了这个数的编码上。

✗ 错误
-128 sign-magnitude: 10000000   <- that pattern means -0
✓ 正确
-128 sign-magnitude: no representation at width 8
-128 two's complement: 10000000

什么时候真的需要查补码

读传感器寄存器
温度寄存器返回 0xFF9C。按无符号读是 65436,这不可能是温度。按位宽 16 看补码那一行是 -100,配合 0.1 °C 的刻度因子,传感器说的是 -10.0 °C。
排查字段不带类型的协议
Modbus、CAN 以及多数二进制遥测传的都是不带符号信息的原始字。客户端和设备对一个值有分歧时,把同一个字的两种读法都看一遍,通常就能定位是哪一侧假设错了。
计算机组成原理作业
原码、反码、补码、移码是这门课的标准四件套。在同一位宽下并排看,差别是看出来的,不是背出来的。
追查整数溢出
计数器从 2147483647 跳到 -2147483648 时,把两者都按 32 位位型看一眼,就能看到进位落进了符号位。这个值并没有变成乱码,它严格按编码的规则回绕了。
写序列化代码
在信任一份手写编码器之前,每个位宽各取一个负数在本页核对一次。符号处理写错很容易,而且产出的字节在第一个真正的负数到来之前看上去毫无问题。

四种编码分别是怎么构造的

原码
最高位是符号位,其余 n-1 位当作普通无符号数读,就是数值的绝对值。范围 -(2^(n-1)-1)2^(n-1)-1,对称,有两个零。IEEE 754 浮点数用的就是这种布局。
反码
负数是其绝对值的逐位取反,等价于 2^n - 1 - x。范围和两个零都与原码相同。它的加法需要循环进位,而这正是补码要消掉的麻烦。英文里 ones' complement(反码)的撇号在 s 之后、two's complement(补码)在 s 之前,不是笔误:前者相对于全 1 的字,后者相对于一个 2 的幂。
补码
负数 -x 存成 2^n - x。范围 -2^(n-1)2^(n-1)-1,刻意不对称,只有一个零。加法、减法以及乘法低位字的运算全都与符号无关,这就是它胜出的全部理由。
移码
存的是 value + 2^(n-1),于是 -2^(n-1) 变成全 0,位型的无符号大小顺序与它们编码的数值顺序一致。它等于补码把最高位翻转。注意命名陷阱:IEEE 754 的指数字段偏移是 2^(e-1)-1,比这里用的少 1。
为什么运算要用 BigInt
JavaScript 会先把 &|~ 和移位的操作数转成 32 位整数再运算、再转回来,于是 64 位的值会丢掉高一半而不抛出任何错误。本页的每一次转换都在任意精度整数上完成,这也是 64 位边界值在这里是精确的原因。

怎样才能把有符号数处理对

任何事之前先把位宽定下来
在你说清字段有多宽之前,一串位是没有数值的。数据手册和调试器对不上,多数时候就是一边按 16 位、另一边按 32 位。
把最负的那个值当特例处理
对它取负在任何位宽下都会溢出——补码里有符号字节的 -(-128) 仍然是 -128。任何求绝对值的代码都得为这个输入准备好,任何测试集都该包含它。
永远不要从数据本身推断符号性
看多少遍位都判断不出一个字段是不是有符号的。这条信息要从数据手册、schema 或结构体定义里拿;靠猜能一直管用,直到线上出现第一个负数。
扩宽时要做符号扩展
把 8 位的 0xFB 塞进 16 位字段写成 0x00FB,-5 就变成了 251。扩宽一个有符号值意味着把符号位复制过去,得到 0xFFFB
优先用语言自带的转换
JavaScript 的 BigInt.asIntN、Python 的 int.from_bytes(..., signed=True)、C 的定宽类型,都把意图写清楚了并且处理好了边界。手写的 ~x + 1 才是位宽 bug 的来源。

补码常见问题

一句话说清补码是什么?
它规定负数 -x2^n - x 的位型来存,这样加法和减法共用同一套电路,而且整条数轴上只有一个零。
补码怎么算?手算的步骤是什么?
先把绝对值写成二进制,逐位取反,然后加 1。以 8 位的 5 为例:000001011111101011111011。只做取反那一步得到的就是反码,所以反码和补码永远差 1。
为什么一个有符号字节装得下 -128 却装不下 +128?
补码的范围是刻意不对称的。n 位覆盖 -2^(n-1)2^(n-1)-1,因为它不像原码和反码那样浪费一个位型去表示负零,多出来的那一格落在了负数一侧。
11111011 到底是 -5 还是 251?
都是,而且光看这串位是分不出来的,取决于产生它的系统声明的类型。所以本页的反查区把每一种读法同时列出来,而不是替你挑一个——按你的 int8_t 还是 uint8_t 去取对应那一行。
移码是什么?在哪儿会遇到它?
移码(也叫偏移码、增码)存的是 value + 2^(n-1),于是最小值变成全 0,把原始位型当无符号数排序的结果与按有符号值排序一致。它出现在 ADC/DAC 的输出和某些音频采样格式里。注意 IEEE 754 的指数字段用的偏移是 2^(e-1)-1,比这里的少 1,两个数不能互相搬用。
8 位和 4 位的移码范围各是多少?
移码存的是 真值 + 2^(n-1),所以它能表示的范围与补码完全相同:8 位是 -128 到 127,4 位是 -8 到 7。变的只是位型的排布——最小值对应全 0,最大值对应全 1,把位型当无符号数从小到大排,得到的正是数值从小到大的顺序。
原码和反码现在还有人用吗?
整数上基本没有了——现役 CPU 几乎全用补码,C23 更是把补码定为强制。它们仍然重要,一是因为 IEEE 754 浮点数保留了原码式的布局,二是因为计算机组成原理的考题还在考。
正数的补码和原码相同吗?
相同,反码也相同——正数在这三种编码里是同一个位型,零也是(只算正零那一个)。差别只出现在负数上。移码是唯一的例外:正数的移码与另外三种都不同,因为它对每一个值都加了 2^(n-1) 的偏移。
负零是什么?它有什么影响?
在原码里 0000000010000000 都表示零;在反码里是 0000000011111111。于是两个数值相等的量按位比较却可能不相等。补码只有一个零,这一下消掉了一整类硬件特例。
我输入的内容会被发到服务器吗?
不会。页面把转换引擎发给浏览器,在你的设备上运行。寄存器 dump 和固件里的值往往来自不能外传的系统,这里不需要你信任任何承诺——打开网络面板即可确认,没有任何请求发出。