写在前面:学习go语言基础的时候了解到int8的数值表示范围为-128~127,对这个结论性的结果表示了解,但仔细推敲发现自己还是没懂其所以然,查阅相关博客遂成此篇,原理为大一学的数字逻辑内容。
背景知识补充:
机器数:
一个数在计算机中的二进制表示方式,叫做这个数的机器数。机器数是带符号的,计算机用最高数位存放符号,正数为 0,负数为 1。
例如:
var number int8 = 3
对应的机器数为0000 0001 (0表示整数,1表示负数)
原码:
原码就是符号位加上真值的绝对值。比如下面这个
[+1]原 = 0000 0001
原码是最容易理解的。因为第一位是符号位,所以 8 位的二进制原码的取值范围是
[11111 1111,0111 1111] 即 [-127,127]
反码:
正数的反码是它本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反
[+1] = [0000 0001]原 = [0000 0001]反
这样的话,如果一个反码表示的是负数,你无法直观的看出它的数值,通常需要转化成原码再进行计算。
补码:
整数的补码就是它本身,负数的补码为源码基础上,符号位不变,其余位取反,末位+1,等价于在反码的基础上+1
[+1] = 原码[0000 0001] = 反码[0000 0001] = 补码[0000 0001]
[-1] = 原码[1000 0001] = 反码[1111 1110] = 补码[1111 1111]
原码->反码->补码的引入原理
为简化计算机的运算设计,让符号位参与运算,减法可视为加上一个负数
例如;
十进制的表达式 1-1=0
1-1 = 1+(-1) = 原码[0000 0001] + 源码[1000 0001] = 源码[1000 0010] = -2
结论:源码让符号位参与运算,对于减法来说,结果是不准确的,这就是为何计算机内部不使用原码表示一个数
为解决原码减法存在的问题,引入反码
1-1 = 1+(-1) = 原码[0000 0001] + 源码[1000 0001]=
反码[0000 0001] + 反码[1111 1110]= 反码[1111 1111] = 原码[1000 0000]=-0
结论:反码计算减法,真值部分是正确的,但是存在+0和-0的问题,两个编码[0000 0001]和[1000 0000]两个编码表示0
为解决补码存在的+0 和 -0问题,引入补码
1-1 = 1+(-1)= 原码[0000 0001] + 源码[1000 0001]=
补码[0000 0001] + 补码[1111 1111] = 补码[0000 0000] = 原码[0000 0000]
结论:通过引入补码(反码负数时符号位不变,末位加一)实现0的唯一编码
因此可以用[1000 0000]表示-128,此时补码的数值表示范围为[-128,127]
注意:-128没有原码和反码表示