作者:消失得珍贵_Cjh_662 | 来源:互联网 | 2023-08-06 14:47
今天这篇文章非常基础。前几天看到的go一道题目,其实和go本身并没有多大关系。funcmain(){问b的值是多少?如果直接说128,那可能还需要再去补补,毕竟int8的范围在『-
![](https://img.php1.cn/3cd4a/1eebe/cd5/60405fda58cd0acd.webp!large)
同理,补码表示形式也是人脑无法直观看出数值的,也需要转化成原码再计算其数值。
从上面可以看出,原码,反码和补码是完全不同的,只有原码才是被人脑直接识别并用于计算表达方式的。为什么还需要反码和补码?
对于计算机来说,加减乘除已经是基础的运算了,要设计的尽量简单,计算机识别 “符号位”显然会让计算机的基础电路设计变得复杂。于是想到把符号位也参与到运算中。我们知道,根据运算法则,减去一个数等于加上一个负数。1-1 = 1+(-1) = 0 因此计算机可以只有加法没有减法。
我们先看原码,十进制的表达式:1-1=0
![](https://img8.php1.cn/3cdc5/1850a/882/b685ef4641904640.png!large)
如果用原码表示,让符号位也参与运算,显然对于减法来说,结果不是正确的。这也就是为何计算机内部不使用原码表示一个数。
接着,为了解决原码做减法的问题,出现了反码:
![](https://img8.php1.cn/3cdc5/1850a/882/fa246a2d8b9c030d.png!large)
可以发现,如果使用反码计算减法,结果的真值的部分是正确的,但是引发了新的问题,虽然在理解上 +0 和 -0 是一样的,但是 0 带符号是没有任何意义的。而且会有 [0000 0000] 和 [1000 0000] 两个编码表示0。
补码终于要闪亮登场了。
![](https://img8.php1.cn/3cdc5/1850a/882/48432ecff3e953ad.png!large)
这样,0用[0000 0000] 表示,之前的 -0 问题就不存在了,而且可以用[1000,0000] 表示-128:
![](https://img8.php1.cn/3cdc5/1850a/882/2d5b8e9be36b674f.png!large)
在用补码运算的结果中,[1000 0000]补 的值就是 -128。实际上是使用之前的 -0的补码来表示 -128,所以 -128 并没有原码和反码的表示。这也是为什么 int8 使用原码或者反码表示的范围为[-127,127]。使用补码,不仅仅修复了 0 的符号以及存在两个编码的问题,而且还能多表示一个最低数。
好了,我们再回到问题的本身。因为 var b int8 = -128 / a 不是常量表达式,因此 untyped 常量 -128 隐式转换为 int 8类型(和a一样),所以 -128 / a 的结果是 int8 类型,值是 128。超出了 int8 的范围,因为结果不是常量,允许溢出,128的二进制表达式是[1000 0000],正好是 -128 的补码,因此答案是 -128。
参考文章