📓 Archive

COMPLEMENT

FGJ: Create:2024/10/23 Update: [2024-11-09]

  • Intro(Complement) #

    • 重新认识计算机中的数字表示 #

      主要以一个字节,8比特位进行分析

      首先要知道计算机中的数字表示有空间限制,比如 java 中 byte 类型就用一个字节(8 bit)表示,而 int 得用 4byte(32 bit)。而且 java 默认都是有符号的,也即第一个比特位表示符号,一个byte 类型的变量可表示的值就是 \(00000000\) - \(11111111\)

      还有一点至关重要,就是进位后的值超出 8 位后会截断。比如 \(11111111 + 1 = 1{\hspace{0.5em}}00000000 ==截断==> 00000000 \),要不然就没法循环了,跟钟表一样,到极限得归位。

      至于这些值表示的实际意义,可以在下面慢慢进行分析。(先不用考虑补码)
      1).: 首先分析正数,总共 8 位,一个符号位占一个[0],剩下的 7 位表示值的话就就是 \(00000000\) - \(01111111\) 表示数值 0 到 127,这个毋庸置疑的。
      2).: 不管一个负数怎么表示,都应该符合我们的理性认知。比如 -1 + 1 的值肯定是 0 的。
      3).: 现在有了正数值比如 1 (\(00000001\)),加一操作后肯定等于 0。也即 \(00000001\) + \(8(*) = 00000000\)
      4).: 目前只有让 \(8(*)\) 这个未知值在加完后整体位溢出,被截断,才能达到加完一个值后更小。
      5).: 所以此处的 \(8(*)\) 二进制表示应该是 \(11111111\),加完 \(00000001\) 后得到 \(1{\hspace{0.5em}}00000000\),截断,然后正好等于 \(00000000\)
      6).: 所以才让这个二进制 \(11111111\) 表示的 -1。

      7).: 其他情况依次了类推,重要的是理解截断才能循环。再举个例子(-128)。
      8).: 已知上述得出的 -1\((11111111)\),和127\((01111111)\),所以 -128 \(8(*)\) + 127 \(01111111\) = -1 \(11111111\)
      9).: 后面的值在二进制表示上要比被加数大,所以这次不用截断,给 \(8(*)\) 值设为 \(10000000\) 即可。也就是 -128 = \(10000000\)

      为了更好的理解数据的分布,可以画一个圆来表示,方便记忆。

    • 认识补码 #

      其实上述得出的二进制表示在计算机中被成为补码,不管是正数的也好,还是负数的也好。只是正数的补码与原码相同,而负数的补码与原码的关系可以推算出来,比如:
      \([-128_补 = 10000000]\) 减一后 ==> \([01111111]\) 取反 ==> \([128_{补|原} = 10000000]\),注意 \(10000000\) 是更多字节中的表示的正数值 128,而在一个字节里面只能表示有符号位的负数。
      \([-1_补 = 1111111]\) 减一后 ==> \([11111110]\) 取反 ==> \([1_{补|原} = 00000001]\)
      \([-2_补 = 1111110]\) 减一后 ==> \([11111101]\) 取反 ==> \([2_{补|原} = 00000010]\)

      也就是对于一个负数来说,补码等于它的正数值按位取反加一

    • 辅助验证 #

  • Reference #


comments powered by Disqus