「$((〜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

署名された番号は通常、次の場所に保存されます。2の報酬表現する:

...
-4 = 1100
-3 = 1101
-2 = 1110
-1 = 1111
 0 = 0000
 1 = 0001
 2 = 0010
 3 = 0011
...

つまり、2のような数字を取ると、ビット単位で0010と解釈されます。ビット否定をすると1101になりますが、これは-3を表現したものです。

答え2

これは2の補数演算の結果です。

~これはビット単位の否定で、演算中のすべてのビットを反転します。 2の補数演算は、すべてのビットを反転し、1を加算する方法で動作します。ビットだけを反転しただけで1を加算しなかったため、反転後に1を引いた同じ数字が得られます。

Wikipediaには2の報酬に関する良い記事があります。ここ

たとえば、

  • イ・ジンスロ30011
  • -3 in(2の補数)2進数は1101
  • 反転すると、まだ1を追加していないので-40011になります。1100

答え3

~ 演算子はビット NOT 演算子です。それを使用することは数字を否定することとは異なります。

~からウィキペディア、ビットごとのNOT演算は、値の2の補数から1を減算するのと同じです。

x = −x − 1 ではない

2進数を否定することは、2の補数値を取るのと同じです。

~NOT 演算子 = を使用して補数値を取得します。

簡単に言えば、〜バイナリ表現のすべてのビットを反転します。

たとえば、

33(10進数)= 0x00100001(8ビット2進数)

~33 = ~0x00100001 = 0x11011110 = -34(10 進数)

あるいは、小数演算では、~x = -x - 1式を使用します。

~33 = -33 - 1 = -34

そして

~255 = -255 - 1 = -256

答え4

問題は〜がビット演算子であるということです。したがって、予想よりも多くのビットを否定しています。結果を16進数に変換すると、これをよりよく見ることができます。たとえば、次のようになります。

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を避けるには、ビットAND演算子である&を使用する必要があります。

関連情報