补码及转换
- 推荐资源
- 整数在计算机中均以补码形式存在
- 32位有符号整数(int32)取值范围为( − 2 31 ∼ 2 31 − 1 -2^{31} \sim 2^{31}-1 −231∼231−1)
- 有符号整数最高位代表符号,0表示正数,1表示负数
- 原码:一个整数按照绝对值的大小转化成二进制的数
- 反码:将二进制数按位取反
- 补码:反码加一
负数从真值求补码
- 先求出其原码
- 求其反码
- 反码加一
如求-20的补码
其原码为00010100;其反码为11101011;其补码为11101100
负数从补码求真值
- 补码减一
- 求其反码
- 得到原码,取相反数
如11101100的真值为
减一为11101011;取反为00010100;取相反数为-20
二进制运算
- 加法运算
- 两个机器数相加的补码可以先通过分别对两个机器数求补码,然后再相加得到,在采用补码形式表示时,进行加法运算可以把符号位和数值位一起进行运算(若符号位有进位,导致了益出,则直接舍弃),结果为两数之和的补码形式
- 35+(-18)
- 35的补码为00100011;-18的补码为11101110;二者相加,溢出舍去,为00010001(17)
- 减法运算等价于加上一个相反数
常用位运算
按位与&
- 参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0
&
可以用来对某些特定的位清零&
可以用来取某个数中某些指定的位- 不同长度如int8类型和int32类型进行按位与,则首先会将int8类型按照其符号位向左填充
- 将英文字母转换为大写
('a' & '_') = 'A'
- 消除数字n的二进制表示中最后一个1
n & (n-1)
T191: 位1的个数
func hammingWeight(num uint32) int {
count:=0
for num!=0 {
num=num & (num-1)
count++
}
return count
}
T461: Hamming距离
func hammingDistance(x int, y int) int {
return hammingWeight(x)+hammingWeight(y)-2*hammingWeight(x&y)
}
func hammingWeight(num int) int {
count:=0
for num!=0 {
num=num & (num-1)
count++
}
return count
}
T231: 2的幂
func isPowerOfTwo(n int) bool {
if n>0 {
return n & (n-1)==0
} else {
return false
}
}
按位或|
- 参与运算的两个值,如果两个相应位中有一个1,则为1,否则为0
|
可以用来把某些特定的位置设为1- 将英文字母转换为小写
('A' | ' ') = 'a'
按位异或^
- 参与运算的两个值,如果两个相应位相同为0,否则为1
^
可以实现两个值的交换,而不使用临时变量
a := 999
b:= -1
a = a ^ b
b = a ^ b
a = a ^ b
fmt.Println(a, b)
// -1 999
- 将英文字母大小写互换
('a' ^ ' ') = 'A'
- 判断两个数是否异号
a := -1
b := 2
return (a ^ b) < 0
取反^
- 注意与异或的位置不同
- 对有符号类型,等价于进行加一取相反数操作
a := 3
b := -3
fmt.Println(^a, ^b)
// -4 2
- 加一操作
n = -^n
减一操作
n = ^-n
左移运算符<<
- 二进制位全部左移若干位
- 左边的二进制丢弃,右边补0
- 对于正数来说,左移相当于乘以2
右移运算符>>
- 二进制位全部右移若干位
- 正数左补0,负数左补1
- 对于正数来说,右1移相当于除以2
fmt.Println(-14 >> 2)
// -4