七叶笔记 » golang编程 » golang的原码、反码和补码再回顾(位运算)

golang的原码、反码和补码再回顾(位运算)

上次

我在这篇文章中专门讲了带符号数据存储规则。今天再结合原码、反码和补码再来验证一下。

先从二进制规则说起:

原码:

数值的原码如果是正数,原码是它本身,负数第一位为1

比如 4,它的原码是0000 0100 ,-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

-13

127+116

244

-12

127+117

245

-11

127+118

246

-10

127+119

247

-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的位运算就完全无问题了。

 &            与  AND    两个都为1才为1
  |            或 OR      两个有一个为1才为1
  ^           异或 XOR   两个要相异
  &^         位清空 (AND NOT)  a &^ b == a & (^b),把b按位取非之后和a做与
  

 func main() {
    fmt.Println(6 & 11)   
    fmt.Println(6 | 11)
    fmt.Println(6 ^ 11)
    fmt.Println(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

用代码验证,完全一致。下面再用负数算一次:

 package main

import (
"fmt"
)

func main() {
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= 1111 1011 =-1后 1111 1010取反1000 0101 也就是补码-5

-6 ^ 11=1111 0001 =-1后 1111 0000取反1000 1111 也就是补码-15

-6 &^ 11=1111 1010 & (^0000 1011)= 1111 1010 & 1111 0100 =1111 0000

-1后 1110 1111取反1001 0000 也就是补码-16

运行验证:

结果完全正确。golang作为新语言,基本原理和c语言都是一致的。

相关文章