上次https://www.toutiao.com/a6982846927054357004/
《从Golang int8数据类型看数据存储规则》
在本文中,我具体谈到了签名数据的存储规则。今天结合原代码,补全补全再验证一遍。
让我们从二元规则开始:
如果
原码:
值的原码为正,则原码为本身,负数的第一位为1。例如,4的原始代码是0000100,而-4的原始代码是1000 0100。
正数
反码:
的倒数就是它本身负数的补码基于其原始代码,符号位不变,其他位反转。
4,它的补码是0000 0100,而-4的补码是1111 1011。
补码:
的正补码是本身。负数的补码基于其原始代码,符号位不变,其余位反转,最后为1。(即,基于其逆码的1)
4,它的补码是0000 0100,而-4的补码是1111 1100。
结合上一篇文章中的表格:
235
-21
127 108
236
-20
127 109
237
-19
127 110
238
-18
127 111
239
-17
127 112
240
-16
127 113
241
-15
127 114
242
-14
127 115
243
减十三
127 116
244
-12
127 117
245
-11
127 118
246
-10
127 119
一周七天
-9
127 120
248
-8
127 121
249
-7
127 122
250
-6
127 123
251
-5
127 124
252
-4
127 125
253
-3
127 126
254
-2
127 127
255
-1
127 128
你惊讶地发现-4的补码是1111 1100,意思是252,对应的表值正好是252,证明我们之前的猜测完全正确。
结论:计算机中的数值完全以补码的形式存储。
计算机巧妙地将符号位运算,化减法为加法,背后隐藏着化繁为简的巧妙数学原理。
有了补码知识,以后用golang的位运算就没问题了。
当和都为1时,AND只有1。
当其中一个为1时,| OR或仅为1。
异或和异或应该是不同的。
位与非(A b==A (B)),逐位否定B,然后与A
func main(){ 0
fmt。Println(6 11)
fmt。Println(6 | 11)
fmt。普林顿(6 ^ 11)
fmt。普林顿(6 ^ 11)
}6=0000 0110
11=0000 1011
6 11=0000 0010=2
6 | 11=0000 1111=15
6 ^ 11=0000 1101=13
6 ^ 11=0000 0110 (^0000 1011)=0000 0110 1111 0100=0000 0100=4
经过代码验证,完全一样。让我们再次使用负数:
包装主体
导入(
fmt '
)
func main(){ 0
fmt。Println(-6 11)
fmt。Println(-6 | 11)
fmt。Println(-6 ^ 11)
fmt。Println(-6 ^ 11)
}-6=1111 1010
11=0000 1011
-6 11=0000 1010=10
-6 | 11=1111011=-1在1111 1010之后,1000 0101的倒数是-5的补数。
-6 11=1111 0001=-1,1111 0000是1000 1111的倒数,1111是-15的补码。
-6 ^ 11=1111 1010 (^0000 1011)=1111 1010 1111 0100=1111 0000
在-1之后,1110 1111否定1001 0000,这是补码-16。
运行验证:
结果绝对正确。作为一种新的语言,golang的基本原则与C语言是一致的。