Як працює оператор побітового доповнення (~ tilde)?


Відповіді:


281

Пам'ятайте, що негативні числа зберігаються як доповнення двох позитивних аналогів. Як приклад, ось подання -2 у двох доповненнях: (8 біт)

1111 1110

Як ви це отримаєте, це взяти двійкове представлення числа, взяти його доповнення (перевернути всі біти) та додати одне. Два починається як 0000 0010, і перевернувши біти, ми отримаємо 1111 1101. Якщо додати один, ми отримаємо результат вище. Перший біт - це бітовий знак, що передбачає негатив.

Тож давайте подивимось, як ми отримуємо ~ 2 = -3:

Ось ще два:

0000 0010

Просто переверніть всі біти і ми отримаємо:

1111 1101

Ну, як виглядає -3 у доповненні двох? Почніть з позитивного 3: 0000 0011, переверніть всі біти до 1111 1100 і додайте один, щоб стати від’ємним значенням (-3), 1111 1101.

Отже, якщо ви просто інвертуєте біти в 2, ви отримаєте їхнє додаткове представлення -3.

Оператор комплементу (~) ПОВІДОМЛЕННЯ БІТИ. Інтерпретувати ці біти залежить від машини.


43
Ще одне, що, можливо, слід зазначити, що фліп називається доповненням 1s, перш ніж додавати 1.
Chris S

3
Це може допомогти іншим, хто не знає про доповнення одного і про доповнення двох. Про них читайте тут. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai

1
Хіба це не біт НЕ оператор?
Бреден Кращий

3
Звідки машина знає, що отримує два додаткові від’ємні числа замість більшого додатного числа? Це через систему типів відповідної мови, яка вказує, що тип є підписаним int проти неподписаним?
GL2014

@ GL2014 Я думаю, ти там відповів на власне запитання. На моє розуміння, це, як машина була розроблена для роботи в першу чергу.
гекідхарш

40

~ перевертає біти у значення.

Чому ~2це -3стосується того, як числа представлені порозрядно. Числа представлені як доповнення двох .

Отже, 2 - двійкове значення

00000010

І ~ 2 перевертає біти, тому значення тепер:

11111101

Що, є двійкове представлення -3.


2
Чи не 11111101 == десятковий 253 проти -3?
AKS

10
Залежить, представляє це підписане чи непідписане ціле число.
дріс

18

Як згадували інші, ~просто перевернуті біти (змінюється один на нуль і нуль на один) і з двох доповнюють ви отримуєте результат, який ви побачили.

Одне слід додати, чому використовується доповнення двох, це так, що операції над від’ємними числами будуть такими ж, як і на додатних числах. Подумайте, -3як число, до якого 3слід додати нуль, і ви побачите, що це число 1101, пам’ятайте, що двійкове додавання - це як базове шкільне (десяткове) додавання, яке ви переносите лише на два, а не на 10 .

 1101 +
 0011 // 3
    =
10000
    =
 0000 // lose carry bit because integers have a constant number of bits.

Тому 1101це -3, фліп біти , які Ви отримуєте , 0010який є два.


8

Ця операція є доповненням, а не запереченням.

Вважайте, що ~ 0 = -1, і працюйте звідти.

Алгоритм заперечення - це "доповнення, збільшення".

Ти знав? Існує також «порозрядне доповнення» , де зворотні числа є симетричними, і вона має як 0 і -0.


6

Я знаю, що відповідь на це питання розміщена ще довго, але я хотів поділитися своєю відповіддю за те саме.

Для пошуку доповнення чисельного числа спочатку знайдіть його двійковий еквівалент. Тут десяткове число 2представлено як 0000 0010у двійковій формі. Тепер беремо його доповнення, перевернувши (перевернувши всі 1 у 0 і всі 0 в 1) усі цифри його двійкового подання, що призведе до:

0000 0010 → 1111 1101

Це доповнення десяткового числа 2. А оскільки перший біт, тобто біт знака дорівнює 1 у двійковому числі, це означає, що знак є негативним для числа, яке він зберігає. (тут вказане число не 2, а доповнене число 2).

Тепер, оскільки числа зберігаються як доповнення 2 (беручи доповнення числа плюс одне), щоб відобразити це двійкове число 1111 1101, у десятковій формі , спершу нам потрібно знайти його 2 доповнення, яке буде:

1111 1101 → 0000 0010 + 1 → 0000 0011

Це доповнення 2-х. Десяткове подання двійкового числа, 0000 0011є 3. І, оскільки бітовий знак був один, як було сказано вище, тому отримана відповідь така -3.

Підказка: Якщо ви уважно читаєте цю процедуру, то ви б помітили, що результатом для оператора комплементу є насправді, число (операнд - до якого застосовується цей оператор) плюс одне з негативним знаком. Ви можете спробувати це і з іншими номерами.


Чому його додають двічі? Я бачу add, flip, add. 0010-> 0011-> 1100->1101
Бреден Кращий

1
Це фліп, перевернути, додати. Перший фліп для доповнення 1. А оскільки він зберігається в додатку 2 у системі, коли вам потрібно відобразити число, воно покаже доповнення 2 із числа, що зберігається (тобто, другий фліп та додавання).
Хіманшу Агарвал

Але хіба не перевернути (flip (2)) просто 2? 0010 1101 0010
Бреден Кращий

Так, це буде лише 2. Але оскільки, коли біти зберігаються в пам'яті, найбільш значущим був біт 1, який згодом зробить число негативним, як пояснено у відповіді вище.
Хіманшу Агарвал

1
З того, що ви описуєте, і все, що я досліджував, це не доповнення двох, а "регулярне" доповнення, або трохи НЕ. У логіці NOT 0 = 1і NOT 1 = 0. У чотирибітній системі NOT 0011(3) = 1100(12 без знаків, -4 підписано). Як я розумію, доповнення двох визначається як (NOT n) + 1і використовується для пошуку негативного аналога числа незалежно від кількості бітів. Таким чином, 2c(5) = -5. Бачите, зараз це має ідеальний сенс. До тих пір, як ви називаєте цю операцію, що це: побіжно НЕ.
Braden Best

4

int a = 4; System.out.println (~ a); Результат буде: -5

'~' будь-якого цілого числа в java являє собою доповнення 1 числа no. наприклад, я беру ~ 4, що означає в двійковому поданні 0100. По-перше, довжина цілого числа становить чотири байти, тобто 4 * 8 (8 біт за 1 байт) = 32. Отже, в системній пам'яті 4 представлено як 0000 0000 0000 0000 0000 0000 0000 0100 зараз ~ оператор виконує доповнення 1 на вищевказаному двійковому номері

тобто 1111 1111 1111 1111 1111 1111 1111 1011-> 1 є доповненням найбільш значущий біт являє собою знак no (або - або +), якщо він 1, тоді знак є "-", якщо це 0, тоді знак є "+" відповідно до це наш результат - від'ємне число, у java від'ємні числа зберігаються у формі 2 доповнення, набутий результат ми маємо перетворити у 2 доповнення (спочатку виконаймо доповнення 1 та просто додай 1 до 1 доповнення). всі вони стануть нулями, крім найбільш значущого біта 1 (який є нашим знаковим поданням числа, що означає залишки 31 біт 1111 1111 1111 1111 1111 1111 1111 1011 (отриманий результат ~ оператора) 1000 0000 0000 0000 0000 0000 0000 0000 0100 (додаток 1)

1 (доповнення 2)

1000 0000 0000 0000 0000 0000 0000 0101 зараз результат -5 перевірте це посилання на відео <[Біт мудрі оператори в Java] https://youtu.be/w4pJ4cGWe9Y


2

Просто ...........

Як доповнення 2 до будь-якого числа, ми можемо обчислити, перевернувши всі 1 на 0 і навпаки, ніж додамо до нього 1.

Тут N = ~ N дає результати - (N + 1) завжди. Оскільки система зберігає дані у формі доповнення 2, це означає, що вона зберігає ~ N так.

  ~N = -(~(~N)+1) =-(N+1). 

Наприклад::

  N = 10  = 1010
  Than ~N  = 0101
  so ~(~N) = 1010
  so ~(~N) +1 = 1011 

Тепер точка - звідки походить Мінус. Моя думка, припустимо, у нас є 32-розрядний реєстр, що означає 2 ^ 31 -1 біт, що бере участь в роботі, і для відпочинку один біт, який змінюється в попередніх обчисленнях (доповненнях), зберігається як біт знаків, який зазвичай 1. І отримаємо результат як ~ 10 = -11.

~ (-11) = 10;

Вищезазначене справедливо, якщо printf ("% d", ~ 0); отримуємо результат: -1;

Але printf ("% u", ~ 0), ніж результат: 4294967295 на 32-бітній машині.


1

Оператор побітового доповнення (~) є одинарним оператором.

Він працює відповідно до наступних методів

Спочатку він перетворює задане десяткове число у відповідне двійкове значення. У випадку 2 він спочатку перетворює 2 до 0000 0010 (у 8 бітне двійкове число).

Тоді він перетворює всі 1 в число в 0, а всі нулі в 1; тоді число стане 1111 1101.

тобто 2-х доповнення представлення -3.

Для того, щоб знайти неподписане значення за допомогою доповнення, тобто просто перетворити 1111 1101 в десятковий (= 4294967293), ми можемо просто використовувати% u під час друку.


1

Я думаю, що для більшості людей частина плутанини походить від різниці між десятковим числом і підписаним двійковим числом, тому давайте уточнимо його спочатку:

для людського десяткового світу: 01 означає 1, -01 означає -1, для двійкового світу комп'ютера: 101 означає 5, якщо він не підписаний. 101 означає (-4 + 1), якщо він підписаний, коли підписана цифра знаходиться в положенні x. | х

тому перевернутий біт 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3, плутанина виникає в результаті змішування підписаного результату (101 = -3) та несигналізованого результату (101 = 5)


1

tl; dr ~ перегортає шматочки. В результаті знак змінюється. ~2- від’ємне число ( 0b..101). Для виведення негативних чисел rubyдруку -, а потім два доповнення ~2:-(~~2 + 1) == -(2 + 1) == 3 . Позитивні числа виводяться як є.

Є внутрішнє значення та його рядкове подання. Для натуральних чисел вони в основному збігаються:

irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2

Останній еквівалентний:

irb(main):003:0> 2.to_s
"2"

~гортає біти внутрішнього значення. 2є 0b010. ~2є 0b..101. Дві крапки ( ..) представляють нескінченну кількість 1s. Оскільки найзначніший біт (MSB) результату 1, результат - від’ємне число ( (~2).negative? == true). Для виведення негативних чисел rubyдруку -, а потім два доповнюють внутрішнє значення. Доповнення двох обчислюється перегортанням бітів, а потім додаванням 1. Доповненням двох 0b..101є 3. Як такий:

irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3

Підсумовуючи це, він перегортає шматочки, що змінює знак. Щоб вивести негативне число, яке воно друкує -, тоді ~~2 + 1( ~~2 == 2).

Причина rubyвиведення негативних чисел на кшталт цього полягає в тому, що вона розглядає збережене значення як доповнення двох до абсолютного значення. Іншими словами, зберігається те, що зберігається 0b..101. Це від’ємне число, і як таке - це доповнення якоїсь дві величини x. Щоб знайти x, це два доповнення 0b..101. Що є двома доповненнями двох доповненнями x. Що є x(наприклад ~(~2 + 1) + 1 == 2).

Якщо ви звернетесь ~до негативного числа, воно просто переверне біти (що все-таки змінить знак):

irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2

Більш заплутаною є те, що ~0xffffff00 != 0xff(або будь-яке інше значення з MSB рівне 1). Давайте спростимо це небагато: ~0xf0 != 0x0f. Це тому, що це трактує 0xf0як позитивне число. Що насправді має сенс. Так, ~0xf0 == 0x..f0f. Результат - від’ємне число. Доповненням двох 0x..f0fє 0xf1. Так:

irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"

У разі , якщо ви не збираєтеся застосовувати оператори побітового до результату, ви можете розглянути в ~якості -x - 1оператора:

irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2

Але це, мабуть, не надто корисне.

Приклад Скажімо, вам дають 8-бітну (для простоти) маску, і ви хочете обчислити кількість 0s. Ви можете їх обчислити, перегортаючи біти і викликаючи bit_length( 0x0f.bit_length == 4). Але ~0xf0 == 0x..f0f, таким чином, ми повинні вирізати непотрібні шматочки:

irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4

Або ви можете скористатися оператором XOR ( ^):

irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"

0

Спочатку ми повинні розділити дану цифру на її двійкові цифри, а потім відмінити її, додавши в останню двійкову цифру. Після цього виконання ми повинні дати протилежний знак попередній цифрі тому, що ми знаходимо в комплектації ~ 2 = -3 Пояснення : 2s двійкова форма 00000010 змінюється на 11111101 це доповнення, потім завершене 00000010 + 1 = 00000011, що є двійковою формою з трьох і з -знаком Ie, -3


0

Бітовий оператор - це одинарний оператор, який працює за методом знаків та величин відповідно до мого досвіду та знань.

Наприклад, ~ 2 призведе до -3.

Це тому, що бітовий оператор спочатку представляє число в знаку та величині, яке становить 0000 0010 (8-бітний оператор), де MSB - біт знаків.

Тоді пізніше знадобиться від'ємне число 2, яке становить -2.

-2 представлений як 1000 0010 (8-бітний оператор) за знаком і величиною.

Пізніше він додає 1 до LSB (1000 0010 + 1), що дає вам 1000 0011.

Що становить -3.


0

Javascript tilde (~) примушує задане значення доповнювати - всі біти перевернуті. Це все робить тильда. Це не знак впевненості. Він ні додає, ні віднімає жодної кількості.

0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]

У стандартних настільних процесорах, що використовують мови високого рівня, такі як JavaScript, арифметика з підписом BASE10 є найпоширенішою, але майте на увазі, це не єдиний вид. Біти на рівні процесора підлягають інтерпретації на основі ряду факторів. На рівні «коду» в цьому випадку JavaScript інтерпретуються за визначенням як 32-бітове ціле число (не залишаємо поплавці поза цим). Подумайте про це як квантові, ці 32-бітні представляють багато можливих значень одночасно. Це повністю залежить від перетворювальної лінзи, через яку ви їх переглядаєте.

JavaScript Tilde operation (1's complement)

BASE2 lens
~0001 -> 1110  - end result of ~ bitwise operation

BASE10 Signed lens (typical JS implementation)
~1  -> -2 

BASE10 Unsigned lens 
~1  -> 14 

Все вищезазначене одночасно вірно.


0

В основному дія є доповненням, а не запереченням.

Тут x = ~ x дають результати - (x + 1) завжди.

х = ~ 2

- (2 + 1)

-3

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.