原码,反码,补码 通俗解释

本贴最后更新于 2179 天前,其中的信息可能已经东海扬尘

用二进制表示数字,需要考虑以下几个问题

  1. 表示范围,有正数,负数和 0
  2. 运算方便
  3. 0 只有一种表示,如果两种表示需要在做底层运算时候进行判断,增减性能损失。

原码

如果用二进制表示正数和负数,可以想到用最高为来代表符号位,符号位不参与数值运算

这就是原码,最直观的表示,0 代表正数,1 代表负数。

以 8bit 的 byte 为例,以下均为 byte

0000 0001 为 1,1000 0001 为-1

但是 0000 00001000 0000 均表示 0

运算也不方便,-1+3 和 1+(-3)

 1000 0001
+0000 0011
=1000 0100
= -4?
 0000 0001
+1000 0011
=1000 0100
= 4?

用进位算法肯定是不行的。只能计算绝对值之差,前面加上绝对值大的数的符号。

如果用原码表示,那范围是-127-127.

所以原码满足了问题 1,但是不满足问题 2 和 3

补码

原码的最高为没有参与数值计算,导致 0 有两种表示方法

如果让最高为参与数值计算呢?这样 0 就只有 0000 0000 一种表示方法

同时因为最高为参与了数值运算,所以在进位加法中最高位和其他位的作用一样,都可以参与与其他数对应位的运算中。

比如-1+3 和 1+(-3)

 1111 1111
+0000 0011
=0000 0010
= 2

最高位的进位扔掉,结果为 2,正确。

 1111 1111
+0000 0011
=0000 0010
= 2

所以补码满足了问题 1,3,但是问题 2 还有一个减法需要考虑,而我们可以把减法换成加法
比如 1-3 转换成 1+(-3),问题是 3 的原码怎么转换成-3 的补码

计算补码的方法

public static void main(String[] args) {
        int a = -10;
//        0x8000_0000 = 1000 0000 0000 0000 0000 0000 0000 0000
 for (int i = 0; i < 32; i++) {
            int t = (a & (0x8000_0000 >>> i)) >>> (31- i);
            System.out.print(t);
        }
    }

反码

正常操作都是先说反码再说补码,这里最后说反码是作为原码转换补码的桥梁。

反码的作用是从原码计算出补码 -1 的原码 1000 0001 计算出补码 1111 11111,除最高位取反 +1 就可以。

除最高位取反就是原码的定义。不过我觉得没什么用。

机器数

机器数好像是以补码表示形式存储的,用补码的好处是方便运算,而用原码的好处就方便展示。

可能考虑到程序中运算的时候远远多于展示需要的时间,所以用补码存储吧。

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3454 回帖 • 189 关注
  • 基础
    7 引用 • 2 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...