Why does "$(( ~33 ))" produce -34?

The man page of bash says:

   ! ~    logical and bitwise negation

Signed numbers are usually stored in Two's complement representation:

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

This means if you take a number like 2 it is bitwise interpreted as 0010. After bitwise negation this becomes 1101, which is the representation of -3.


This is the result of two's complement arithmetic.

~ is a bitwise negation that inverts all of the bits being operated upon. Two's complement arithmetic works by inverting all of the bits and adding 1. Since you have only flipped the bits, but not added one, you get the same number, inverted, minus one.

Wikipedia has a good article on two's complement here.

As an example:

  • 3 in binary is 0011
  • -3 in (two's complement) binary is 1101
  • Inverting 0011 gives you 1100, which is -4, since you haven't added 1.

The ~ operator is the bitwise NOT operator. Using it is not the same as negating a number.

From wikipedia, a bitwise NOT operation is equal to taking the two's complement of the value minus one:

NOT x = −x − 1

Negating a binary number is equivalent to taking its two-complement value.

Using the ~ NOT operator = take its one-complement value.

In simpler terms, ~ just flips all the bits of the binary representation.

For your examples:

33 (decimal) = 0x00100001 (8-bit binary)

~33 = ~0x00100001 = 0x11011110 = -34 (decimal)

Or in decimal arithmetics, using the ~x = -x - 1 formula:

~33 = -33 - 1 = -34

and

~255 = -255 - 1 = -256