![为什么“$(( ~33 ))”产生-34?](https://linux22.com/image/31781/%E4%B8%BA%E4%BB%80%E4%B9%88%E2%80%9C%24((%20~33%20))%E2%80%9D%E4%BA%A7%E7%94%9F-34%EF%BC%9F.png)
$ echo $(( 255 ))
255
$ echo $(( 33 ))
33
$ echo $(( ~33 ))
-34
$ echo $(( ~255 ))
-256
$
我的内核是:
$ uname -a
Linux HOSTNAME 3.2.0-40-generic-pae #64-Ubuntu SMP Mon Mar 25 21:44:41 UTC 2013 i686 i686 i386 GNU/Linux
问题: ~
用于否定数字 AFAIK。但为什么会~33
产生-34
以及为什么会~255
产生-256
?
答案1
bash 的手册页说:
! ~ logical and bitwise negation
有符号数通常存储在二进制补码表示:
...
-4 = 1100
-3 = 1101
-2 = 1110
-1 = 1111
0 = 0000
1 = 0001
2 = 0010
3 = 0011
...
这意味着如果你采用像 2 这样的数字,它会按位解释为 0010。按位求反后,它会变成 1101,它是 -3 的表示。
答案2
这是二进制补码运算的结果。
~
是按位求反,反转所有正在操作的位。补码算术的工作原理是反转所有位并加 1。由于您只翻转了位,但没有加 1,所以您得到相同的数字,反转后减一。
维基百科有一篇关于二进制补码的好文章这里。
举个例子:
- 二进制中的 3 是
0011
- -3 在(二进制补码)二进制中是
1101
- 反转
0011
得到1100
,即 -4,因为您还没有加 1。
答案3
~ 运算符是按位 NOT 运算符。使用它与否定一个数字不同。
从维基百科,按位 NOT 运算等于将值的二进制补码减一:
非 x = −x − 1
对二进制数求反相当于取其二进制补码值。
使用 ~ NOT 运算符 = 获取其一补值。
简单来说,~ 只是翻转二进制表示的所有位。
举个例子:
33(十进制)= 0x00100001(8 位二进制)
~33 = ~0x00100001 = 0x11011110 = -34(十进制)
或者在十进制算术中,使用 ~x = -x - 1 公式:
〜33 = -33 - 1 = -34
和
〜255 = -255 - 1 = -256
答案4
问题是~是一个按位运算符。因此,您否定的位比您预期的要多。您可以通过将结果转换为十六进制来更好地看到这一点,例如:
result_in_hex=$(printf "%x" $(( ~33 ))); echo $result_in_hex
ffffffffffffffde
与你所拥有的相比:
result_in_dec=$(printf "%d" $(( ~33 ))); echo $result_in_dec
-34
我假设你的意思是否定 0x33。如果是这样的话,那么这将起作用:
result_in_hex=$(printf "%2x" $(( ( ~ 0x33 ) & 0xFF))); echo $result_in_hex
cc
您还需要使用 & ,它是按位与运算符,以避免开头的所有 ff 。