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

  • Сильная команда таймаута в zsh
  • Совпадение шаблона оболочки и появление регулярных выражений
  • Можно ли создавать псевдонимы, которые влияют на услуги, начиная?
  • bash: синтаксическая ошибка около неожиданного токена `} '
  • Что именно происходит, когда встроенная команда запускается в оболочке?
  • Что означает «/ bin / sh -c nice run-parts -report /etc/cron.daily»?
  • код выхода команды ** перед ** последним?
  • Скобки в условии if: почему я получаю синтаксические ошибки без пробелов?
  • 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 в начале.

    Interesting Posts
    Linux и Unix - лучшая ОС в мире.