go语言写了一段代码,为什么一个字节的有符号位与无符号位 计算后的结果不一样
一、计算机是如何存储数据的
在计算机中,存储一个数的时候,都是以补码的形式存储的
正数:正数的补码就等于它的原码
例如:16 源码:0001 0000 补码:0001 0000 //这就是计算机最终存储的数据
负数:负数的补码是原码除符号位以外都取反,然后 + 1 得来的
例如: -16 源码:1 001 0000 // 计算机在处理负数时最高位代表符号位 所以 最高位的1为 负号 反码:1 110 1111 //符号位不变 其他数据位取反 补码:1 110 1111+1=1 111 0000 //反码+1=补码 这就是计算机最终存储的数据
二、有符号与无符号
无符号:其最高位的1或0,和其它位一样,用来表示该数的大小。
一个字节(1111 1111) 1111 1111=1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0=255;所以无符号的一个字节表示的数据范围是0~255 共 256个;在Go语言中 uint8 范围(0~255)
例如:100 无符号表示:01100100
有符号:最高数称为“符号位”。为1时,表示该数为负值,为0时表示为正值。一个字节(0111 1111) 最高位的0表示正号,0111 1111=+111 1111=+(1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0)=+127
例如:100 有符号表示:01100100 //最高位0 表示 +号, 后七位才是具体数据位
对于有符号数的运算,一律采用补码进行;把减法运算转为加法运行 例如 5-3=5+(-3)
5 补码:0000 0101 -3 补码:1111 1101 相加: 10000 0010 // 由于我们是8位bit运算,我们丢弃溢出位1 最后 是 0000 0010=2
计算:5-7=5+(-7)=-2
5 补码:00000101 -7 补码:11111001 相加: 11111110 (由于符号位为1 所以改数为补码) 反码: 11111101 // 补码-1 源码: 10000010 // 反码除符号位以外取反
对于有符号位的0
源码:1000 0000
反码:1111 1111
补码:1 0000 0000 //去掉溢出位1后 0000 0000
所以对于0 如果采用8bit位 我们规定就用0000 0000 表示,用1000 0000 表示-128
最后我们手动计算该代码
1 源码: 0 000 0001
1 补码: 0 000 0001
127源码: 0 111 1111
127补码: 0 111 1111
1补码+127补码=1000 0000 由于我们程序采用8bit位有符号类型,所以该结果是-128