Julia 位运算符,无论怎样的数值类型,在计算机中都是连续的二进制串。任何的运算实质都是在改变或转移这些二进制串。对数值进行位运算,包括与(And)、或(Or)、非(取反,Not)、异或(Xor)、左移及右移等时,实际是对数据的内存结构进行直接的操作。在一些情况下,直接控制这些二进制串,可以在节约计算资源或提升关键代码性能等方面带来好处。这样的操作常见于通信中的传输协议、编解码或密码学等领域。
需要说明的是,Julia中提供的位运算符仅适用于整型,不能是其他类型,包括浮点型或有理数型等。下表给出了Julia位运算符的示例用法及简单的说明。
其中除了取反是一元的,其他都是二元运算符。
与或非运算
我们以实例首先了解取反操作,例如:
变量m的内容是一个值为50的有符号整数。经过取反后,其内存中的每一个二进制位均被反转,甚至包括符号位。所以取反的结果是数值50变成了-50这个负值。
再看一个无符号数值的例子:
其中值为3的8位无符号整型m的各二进制位同样被逐位反转。因为是无符号的,所以不存在正负值变换的说法,但我们可以通过将其转换到Int64
类型看一下值的变化:
julia> Int64(m)
3
julia> Int64(n)
252
对于与、或及异或运算,在符号变化方面有些不同,例如:
julia> m = Int8(10);
julia> n = Int8(-7);
julia> bitstring(m) # m的二进制结构
"00001010"
julia> bitstring(n) # n的二进制结构
"11111001"
julia> p = m & n # 与操作
8
julia> q = m | n # 或操作
-5
julia> r = m ˇ n # 异或操作
-13
julia> bitstring(p) # 与结果的二进制结构
"00001000"
julia> bitstring(q) # 或结果的二进制结构
"11111011"
julia> bitstring(r) # 异或结果的二进制结构
"11110011"
这三个运算同样会涉及符号位,但结果的符号是可以根据运算的特点进行推断的。例如,正数与负数做与运算时,结果肯定是正数(因为符号位必然是0);而做或运算时,则会得到负数,因为符号位必然是1。
移位运算
同样,左移运算也会涉及符号位,例如:
julia> bitstring(m)
"00001010"
julia> bitstring(m << 1) # 左移1位
"00010100"
julia> bitstring(m << 2) # 左移2位
"00101000"
julia> bitstring(m << 3) # 左移3位
"01010000"
julia> m << 3 # 左移3位后的取值
80
julia> bitstring(m << 4) # 左移4位
"10100000"
julia> m << 4 # 左移4位后的取值
-96
随着值为10的m变量的二进制位不断左移,值会越来越大,但当移动了4个位置后,符号位由0变成了1, m的值也变成了负数。
但右移运算中,Julia区分了是否考虑符号位的情况,分为算术右移及逻辑右移。在算术右移后,数值的正负是不变的,例如:
变量n是负数,符号位是1,算术右移1位后,右侧的二进制位消失,但因为考虑了符号位,所以左侧在补充二进制位时,补上的并不是0而是1,从而保持了符号的表达。
继续对n进行算术右移,会发现:
julia> bitstring(n) # n的二进制结构
"11111001"
julia> bitstring(n >> 1) # 算术右移1位
"11111100"
julia> bitstring(n >> 2) # 算术右移2位
"11111110"
julia> bitstring(n >> 3) # 算术右移3位
"11111111"
julia> bitstring(n >> 4) # 算术右移4位
"11111111"
julia> n >> 4 # 算术右移4位后的取值
-1
当移动了一定的数位后,二进制串中不再有0,结果的值便保持了-1,再算术右移任意的位数,该值都不再变化。
而对于正数来说,不断右移的结果为:
julia> m
10
julia> bitstring(m) # m的二进制结构
"00001010"
julia> bitstring(m >> 1) # 算术右移1位
"00000101"
julia> bitstring(m >> 2) # 算术右移2位
"00000010"
julia> bitstring(m >> 3) # 算术右移3位
"00000001"
julia> bitstring(m >> 4) # 算术右移4位
"00000000"
julia> bitstring(m >> 5) # 算术右移5位
"00000000"
julia> m >> 5 # 算术右移5位后的取值
0
右移了一定位数后,结果值保持为0值,而且不再变化。
正数的这种情况在逻辑右移中也是一样的,例如:
julia> bitstring(m >>> 1) # 逻辑右移1位
"00000101"
julia> bitstring(m >>> 2) # 逻辑右移2位
"00000010"
julia> bitstring(m >>> 3) # 逻辑右移3位
"00000001"
julia> bitstring(m >>> 4) # 逻辑右移4位
"00000000"
julia> bitstring(m >>> 5) # 逻辑右移5位
"00000000"
对负数来说,逻辑右移的效果类似,但是有所不同,例如:
julia> n
-7
julia> bitstring(n)
"11111001"
julia> p = n >>> 1 # 逻辑右移1位
124
julia> bitstring(p)
"01111100"
对于值为-7的n而言,仅移动了一位,结果的值便变成了124这个正数。
一般而言,任何负数只要经过一次逻辑右移便会变成正数,这是因为计算机表达正数的符号位是左侧的0,而一旦逻辑右移,1便会被0补上。
酷客网相关文章:
评论前必须登录!
注册