为什么“$(( ~33 ))”产生-34?

为什么“$(( ~33 ))”产生-34?
$ 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 。

相关内容