Почему «$ ((~ 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 ?

4 Solutions collect form web for “Почему «$ ((~ 33))« производит -34?”

На странице руководства bash говорится:

  ! ~ logical and bitwise negation 

Подписанные номера обычно хранятся в представлении дополнений Two :

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

Это означает, что если вы берете число, равное 2, оно поразрядно интерпретируется как 0010. После побитового отрицания это становится 1101, что является представлением -3.

Это результат арифметики дополнений двух.

~ – поразрядное отрицание, которое инвертирует все используемые биты. Арифметика дополнений 2 работает путем инвертирования всех бит и добавления 1. Так как вы только перевернули биты, но не добавили один, вы получите одинаковое число, инвертированное, минус одно.

В Википедии есть хорошая статья о двух дополнениях.

В качестве примера:

  • 3 в двоичном формате – 0011
  • -3 в (дополнение двух) двоичный – 1101
  • Инвертирование 0011 дает вам 1100 , что равно -4, так как вы не добавили 1.

Оператор ~ является побитовым оператором NOT. Использование его – это не то же самое, что отрицание числа.

Из wikipedia побитовая операция NOT равна принятию двух дополнений к значению минус единица:

NOT x = -x – 1

Отрицание двоичного числа эквивалентно принятию его двухкомпонентного значения.

Использование оператора ~ NOT = принимает значение однокомпонента.

Проще говоря, ~ просто перевертывает все биты двоичного представления .

Для ваших примеров:

33 (десятичный) = 0x00100001 (8-битный двоичный код)

~ 33 = ~ 0x00100001 = 0x11011110 = -34 (десятичный)

Или в десятичной арифметике, используя формулу ~ x = -x – 1:

~ 33 = -33 – 1 = -34

а также

~ 255 = -255 – 1 = -256

Проблема в том, что ~ – бит-мудрый оператор. Следовательно, вы отрицаете больше бит, чем вы, возможно, собираетесь. Вы можете видеть это лучше, преобразовывая результаты в hex, например:

 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 

Вы также должны использовать & which bit-wise и operator, чтобы избежать всех ff в начале.

  • предотвратить " + сделать $ scriptname" и " 31303", который будет показан
  • Копирование родительского каталога в подкаталог без бесконечной петли
  • Почему мой tar в скрипте ведет себя иначе, чем использование tar вручную
  • Найти команды / функцию, имя которой соответствует значению
  • Как получить результаты из «\ 033 [6n» в сценарии sh
  • Расширение оболочки для аргументов?
  • Дополнительное пространство с подсчитанным номером строки?
  • Что означает «-» (двойная тире)? (также известный как «голой двойной тире»)
  • Сценарий оболочки для ожидания пакета из определенного порта
  • Имеет ли внешняя команда, которая принимает команду в качестве аргумента, имеет ограничение на аргумент?
  • Убедитесь, что glob имеет уникальное расширение в bash (или, в общем, в posix)
  • Почему изменение $ PATH влияет на дочерние оболочки, но с изменением $ foo нет?
  • Linux и Unix - лучшая ОС в мире.