计算机是以补码的方式进行存储数据的。一般补码是通过:原码→反码→补码的转换求得。
注:1.此篇以8位二进制为例讲解,即byte类型。
2.byte所占位数8位,取值范围为(-2)^7 ~ 2^7-1 or -128~127。
3.此篇都为十进制转二进制。
例:
20的原码:0 0010100,此处蓝色的0为符号位,即值为正;后面的7位红色数为数值位。
-20的原码:1 0010100。此处蓝色的1为符号位,即值为负;后面的7位红色数为数值位。
以66为例。
原码:0 1000010
反码:0 1000010
补码:0 1000010
-66的原码:1 1000010
-66的补码:1 0111110
-16的原码:1 0010000
-16的补码:1 1110000
-66的原码:1 1000010
-66的反码:1 0111101
-16的原码:1 0010000
-16的反码:1 1101111
-66的反码:1 0111101
-66的补码:1 0111110
-16的反码:1 1101111
-16的补码:1 1110000
总结:
正数的原码,反码,补码是一样的。
负数:以-22为例。
原码 1 0010110
反码 1 1101001 //在原码的基础上,符号位不变,数值位按位取反。
补码 1 1101010 //在反码的基础上,符号位不变,末位+1。
原码→补码的快速转换:
原码 1 0010110
补码 1 1101010 //在原码中,符号位不变,从右往左 找第一个1,这个1左边取反,右边不变。
延伸:计算机中的加法与减法(实际上是补码的相加)
a-b=a[补码]+(-b)[补码]CPU里只有加法器 没有减法器 做a-b运算时,实际上是做了a+(~b)
注意:两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃【例2】。
例1:
golang语言
package main
import "fmt"
func main() {
var a, b uint8
a = 1
b = 255
fmt.Println(a - b)
}
输出值为 正2 。
原因是:首先uint(无符号整型),没有符号位
计算流程 数值 原码 反码 补码
1 00000001 00000001 00000001
-255 11111111 00000000 00000001
负数的 反码与补码 非符号位依然遵循转换逻辑(只是没有符号位)
相加得 00000010 ,转为十进制后为 正2
例2:
package main
import "fmt"
func main() {
var a, b int8
a = -3
b = 127
fmt.Println(a - b)
}
输出值为:正 126 。
计算流程 数值 原码 反码 补码
-3 1 0000011 1 1111100 1 1111101
-127 1 1111111 1 0000000 1 0000001
两个补码相加得 (1)0 1111110 ,转成十进制为 正126
