常见的golang位运算符:
& 位与(bitwise AND)
| 位或 (bitwise OR)
^ 位异或 (bitwise XOR)
&^ 位清空 (AND NOT)
>> 左移 integer >> unsigned integer
<< 右移 integer << unsigned integer
go 位操作符
&
, |
, <<
和 >>
都是常见的运算符,主要说明 ^
, &^
的使用进行说明
-
^
作为一元运算符时表示位反或位补
当作为一元运算符的时候,进行运算时,对其补充一个操作数 m
; 如 ^n
等价于m ^ n
, 然后进行二元计算; 其中m
和n
同类型, 并且规定 当m是有符号整数时,m = -1;当m是无符号整数时,m所有bit位都是 1
。
比如如果n的类型为int8,则m的值为-1;如果n的类型为uint8,则m的值为255。
-
&^
位清空运算
这个运算和被运算变量位置有关系,先看一个例子
package main
import "fmt"
func main() {
x := 2
y := 4
fmt.Println(x&^y)
}
output: 2
计算 x&^y 首先我们先换算成2进制 0000 0010 &^ 0000 0100 = 0000 0010, 表示如果 y
中的 bit 位为 1,则 z
对应 bit 位为 0,否则 z
对应 bit 位等于 x
中相应的 bit 位的值。
一些涉及到位运算的基础概念
真值, 原码,反码,补码
为了让符号位参与基本预算,产生了反码;
为了解决反码运算后产生-0的问题产生了补码;
计算机实际用补码参与运算,获得的结果需要转换成原码。
真值: 有符号数二进制位左边第一个符号位置0后得到的值。
原码: 符号位加真值的绝对值。
反码: 无符号数和正数的反码是其本身,负数的反码是将原码除符号位外的其他位按位取反,即0变1,1变0。
补码: 无符号数和正数的补码是其本身,负数的补码是反码二进制加1
补码的原理
在介绍补码概念之前,先介绍一下"模"的概念:“模”是指一个计量系统的计数范围,如过去计量粮食用的斗、时钟等。计算机也可以看成一个计量机器,因为计算机的字长是定长的,即存储和处理的位数是有限的,因此它也有一个计量范围,即都存在一个“模”。如:时钟的计量范围是0~11,模=12。表示n位的计算机计量范围是,模=。“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。
假设当前时针指向8点,而准确时间是6点,调整时间可有以下两种拨法:一种是倒拨2小时,即8-2=6;另一种是顺拨10小时,8+10=12+6=6,即8-2=8+10=8+12-2(mod 12).在12为模的系统里,加10和减2效果是一样的,因此凡是减2运算,都可以用加10来代替。若用一般公式可表示为:a-b=a-b+mod=a+(mod-b)。对“模”而言,2和10互为补数。实际上,以12为模的系统中,11和1,8和4,9和3,7和5,6和6都有这个特性,共同的特点是两者相加等于模。对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是11111111,若再加1成100000000(9位),但因只有8位,最高位1自然丢失(相当于丢失一个模)。又回到了 00000000,所以8位二进制系统的模为。在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。把补数用到计算机对数的处理上,就是补码。
三者之间的关系
原码-真值-补码操作符运算的优先级
一元运算符具有最高优先级。由于 ++ 和 -- 运算符形成语句,而不是表达式,因此它们不属于运算符层次结构。因此,语句 *p++ 与 (*p)++ 相同。
二元运算符有五个优先级。乘法运算符最强,其次是加法运算符、比较运算符、&&(逻辑与),最后是 || (逻辑或)
优先级 | 操作符 |
---|---|
5 | * / % << >> & &^ |
4 | + - | ^ |
3 | == != < <= > >= |
2 | && |
1 | || |
网友评论