概念

  • 机器数

  • 真值

    • 真值符号部分
    • 真值部分

举例: -1的真值是:1000 0001, 其中真值符号区域为最高位的1,他的真值区域000 0001


  • 原码
1
2
[+1] = 0000 0001
[-1] = 1000 0001
  • 反码:
    • 正数的反码是其本身
    • 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
十进制数带符号位二进制原码带符号位二进制补码
-8N1000
-711111001
-611101010
-511011011
-411001100
-310111101
-210101110
-110011111
-010000000
+000000000
100010001
200100010
300110011
401000100
501010101
601100110
701110111
  • 补码:
    • 正数的补码就是其本身
    • 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码基础上+1)

计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式. 但为什么需要三种不同的编码方式呢?

使用原码,反码和补码的原因

人脑与机器计算的差异

人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减。但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们转而设计出将符号位也参与运算的方法。

反码诞生原因

如果只使用原码,当我们计算1-1=0 => 1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2,这显然不符合我们的预期。

为了解决原码符号位也参与运算做减法的问题, 出现了反码,会到前面的例子,用反码来表示一下:1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0用反码计算减法, 结果真值区域是正确的

再看一个1-2=>[0000 0001]原 + [1000 0010]原= [0000 0001]反 + [1111 1101]反 = [1111 1110]反 = [1000 0001]原,就为-1

但对于0这个特殊的数值. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 且会用[0000 0000]原和[1000 0000]原两个编码表示0,导致浪费。

补码的诞生

于是补码的出现, 解决了0的符号以及两个编码的问题: 1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

重探反码

计算机巧妙地把符号位参与运算, 并且将减法变成了加法, 背后蕴含了怎样的数学原理呢?

将钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢?我们可以:

1
2
3
1. 往回拨2个小时: 6 - 2 = 4
2. 往前拨10个小时: (6 + 10) mod 12 = 4
3. 往前拨10+12=22个小时: (6+22) mod 12 =4

2,3方法中的mod是指取模操作, 16 mod 12 =4 即用16除以12后的余数是4.

所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!

现在的焦点就落在了如何用一个正数, 来替代一个负数. 上面的例子我们能感觉出来一些端倪, 发现一些规律. 但是数学是严谨的. 不能靠感觉.

模运算的定义

定义:对于任意实数x,y,可以有 $$ x \bmod y=x-y\left[\frac{x}{y}\right], \quad y \neq 0 $$ 取下界

-3 mod 2:

1
2
3
4
5
-3 mod 2
  = -3 - 2x[-3/2]
  = -3 - 2x[-1.5]
  = -3 - 2x(-2) // 取下界
  = -3 + 4 = 1

同余

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
同余是数论中的一个概念,指两个整数在除以某个正整数时所得的余数相等,可以用符号 ≡ 表示。具体来说,如果整数 a 和 b 在模 m 的意义下同余,即有:

a ≡ b (mod m)

其中 mod 是取模运算符,表示对两个操作数进行除法运算后取余数的结果。

这个式子的含义是,a 与 b 除以 m 的余数相同。例如,假设 m = 7,a = 25,b = 11,则有:

25 ≡ 4 (mod 7)

11 ≡ 4 (mod 7)

因此,在模 7 的意义下,25 和 11 是同余的。同样地,对于任何整数 k,都有:

25 + 7k ≡ 4 + 7k (mod 7)

这是因为 25 + 7k 和 4 + 7k 在除以 7 后的余数相同。

同余关系在数论中非常重要,因为它可以用于证明和推导各种定理和公式。同时,同余关系还广泛应用于密码学、编码解码等领域。

同余定理的反身性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
同余定理的反身性是指,如果两个整数 a 和 b 模 m 同余,即 a ≡ b (mod m),那么也可以推导出 b ≡ a (mod m)。

例如,假设 a = 7,b = 17,m = 5,则有:

a ≡ 7 ≡ 2 (mod 5)

b ≡ 17 ≡ 2 (mod 5)

因此,a 和 b 在模 5 下是同余的。根据同余定理的反身性,我们可以得出:

2 ≡ a ≡ 7 (mod 5)

2 ≡ b ≡ 17 (mod 5)

这表明在模 5 的意义下,a 和 b 是等价的,它们对于同一模数的余数相同。这个结论符合同余定理的定义,因此同余定理的反身性成立。

同余的线性运算

  • 同余式相加:若 $$ a \equiv b(\bmod m) , c \equiv d(\bmod m) ,则 a \pm c \equiv b d \mathrm{m} (mod m) $$
  • 同余式相乘:若 $$ a \equiv b(\bmod m) , c \equiv d(\bmod m) ,则 a c \equiv b d(\bmod m) $$

一个数的反码, 实际上是这个数对于一个膜的同余数. 而这个膜并不是我们的二进制, 而是所能表示的最大值

  • 2-1=2+(-1) = [0000 0010]原 + [1000 0001]原= [0000 0010]反 + [1111 1110]反 = [0000 0010]补 + [1111 1111]补

-1的反码表示是1111 1110. 如果这里将[1111 1110]认为是原码, 则[1111 1110]原 = -126, 这里将符号位除去(符号位是参与计算的, 正好和溢出的最高位形成正确的运算结果), 即认为是126

1
2
3
4
5
(-1) mod 127 = 126 //负数取模
126 mod 127 = 126

(-1) ≡ 126 (mod 127)
所以:2-1 ≡ 2+126 (mod 127), 这个就是内涵的数学原理
1
2
3
4
5
其实, 在反码的基础上+1, 只是相当于增加了膜的值:
(-1) mod 128 = 127
127 mod 128 = 127

2-1 ≡ 2+127 (mod 128)