Jak działa operator bitowego uzupełnienia (~ tylda)?


Odpowiedzi:


281

Pamiętaj, że liczby ujemne są przechowywane jako uzupełnienie dwóch dodatnich odpowiedników. Jako przykład, oto reprezentacja -2 w uzupełnieniu do dwóch: (8 bitów)

1111 1110

W ten sposób otrzymujesz binarną reprezentację liczby, przyjmując jej uzupełnienie (odwracając wszystkie bity) i dodając jedną. Dwa zaczynają się od 0000 0010, a przez odwrócenie bitów otrzymujemy 1111 1101. Dodanie jednego powoduje otrzymanie powyższego wyniku. Pierwszy bit jest bitem znaku, co oznacza wartość ujemną.

Przyjrzyjmy się więc, w jaki sposób otrzymujemy ~ 2 = -3:

Oto dwa znowu:

0000 0010

Po prostu odwróć wszystkie bity, a otrzymamy:

1111 1101

Jak wygląda -3 w uzupełnieniu do dwóch? Zacznij od dodatniej 3: 0000 0011, odwróć wszystkie bity na 1111 1100 i dodaj jeden, aby uzyskać wartość ujemną (-3), 1111 1101.

Więc jeśli po prostu odwrócisz bity w 2, otrzymasz reprezentację uzupełnienia dwóch -3.

Operator dopełniacza (~) JUST FLIPS BITS. Interpretacja tych bitów zależy od maszyny.


43
Jeszcze jedną rzeczą, o której warto wspomnieć, jest to, że flip jest nazywany uzupełnieniem 1s, przed dodaniem 1.
Chris S

3
Może to pomóc innym, którzy nie są świadomi Uzupełnienia Jednego i Uzupełnienia Dwóch. Przeczytaj o nich tutaj. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai

1
Czy to nie jest bitowy operator NOT?
Braden Best,

3
Skąd maszyna wie, że otrzymuje ujemną liczbę dwóch uzupełnień zamiast wyższej liczby dodatniej? Czy to z powodu systemu typów w danym języku wskazującym, że typ jest znakiem int w porównaniu z niepodpisanym?
GL2014

@ GL2014 Myślę, że odpowiedziałeś na własne pytanie. W moim rozumieniu to przede wszystkim sposób, w jaki maszyna została zaprojektowana.
geekidharsh

40

~ odwraca bity wartości.

Dlaczego ~2to -3ma wspólnego z tym, jak numery są reprezentowane bitowe. Liczby są reprezentowane jako uzupełnienie dwóch .

Zatem 2 jest wartością binarną

00000010

I ~ 2 odwraca bity, więc wartość wynosi teraz:

11111101

Który jest reprezentacją binarną -3.


2
Czy 11111101 == dziesiętny 253 vs -3?
AKS,

10
Zależy, czy reprezentuje liczbę całkowitą ze znakiem lub bez znaku.
driis

18

Jak wspomnieli inni, ~po prostu odwrócone bity (zmienia jeden na zero i zero na jeden), a ponieważ używane jest uzupełnienie dwóch , otrzymujesz wynik, który widziałeś.

Jedną rzeczą do dodania jest to, dlaczego stosowane jest uzupełnienie do dwóch, jest to tak, że operacje na liczbach ujemnych będą takie same jak na liczbach dodatnich. Pomyśl o -3liczbie, do której 3należy dodać, aby uzyskać zero, a zobaczysz, że ta liczba jest 1101, pamiętaj, że dodawanie binarne jest podobne do dodawania do szkoły podstawowej (dziesiętnej), tyle że nosisz jeden, gdy osiągasz dwa, a nie 10 .

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

W związku z tym 1101jest -3, odwracanie bitów dostaniesz 0010który wynosi dwa.


8

Ta operacja jest uzupełnieniem, a nie negacją.

Weź pod uwagę, że ~ 0 = -1 i pracuj stamtąd.

Algorytmem negacji jest „uzupełnienie, przyrost”.

Czy wiedziałeś? Istnieje również „uzupełnienie”, w którym liczby odwrotne symetryczne i ma zarówno 0, jak i -0.


6

Wiem, że odpowiedź na to pytanie została opublikowana dawno temu, ale chciałem udostępnić swoją odpowiedź za to samo.

Aby znaleźć uzupełnienie liczby, najpierw znajdź jej binarny odpowiednik. Tutaj liczba dziesiętna 2jest reprezentowana 0000 0010w postaci binarnej. Teraz bierzemy jego dopełnienie poprzez odwrócenie (odwrócenie wszystkich 1 na 0 i wszystkie 0 na 1) wszystkie cyfry jego reprezentacji binarnej, co spowoduje:

0000 0010 → 1111 1101

Jest to uzupełnienie liczby dziesiętnej 2. A ponieważ pierwszy bit, tj. Bit znaku ma liczbę 1 w liczbie binarnej, oznacza to, że znak jest ujemny dla liczby, którą zachował. (tutaj liczba, o której mowa, to nie 2, ale uzupełnienie 2).

Ponieważ liczby są przechowywane jako uzupełnienie 2 (biorąc uzupełnienie jednego z liczby plus jeden), więc aby wyświetlić tę liczbę dwójkową 1111 1101, w systemie dziesiętnym, najpierw musimy znaleźć uzupełnienie 2, które będzie:

1111 1101 → 0000 0010 + 1 → 0000 0011

To jest uzupełnienie 2. Dziesiętna reprezentacja liczby binarnej 0000 0011, to 3. A ponieważ bit znaku był jednym, jak wspomniano powyżej, więc odpowiedź jest następująca -3.

Wskazówka: Jeśli dokładnie zapoznasz się z tą procedurą, zauważysz, że wynikiem działania operatora dopełniacza jest liczba (operand - na którym ten operator jest stosowany) plus jeden ze znakiem ujemnym. Możesz spróbować również z innymi numerami.


Dlaczego dodaje dwa razy? Widzę add, flip, add. 0010-> 0011-> 1100->1101
Braden Best

1
To klapki, klapki, dodaj. Pierwszy rzut za uzupełnienie 1. A ponieważ jest on przechowywany w uzupełnieniu 2 w systemie, kiedy trzeba wyświetlić liczbę, pokaże uzupełnienie 2 przechowywanej liczby (tj. Drugie odwrócenie i dodanie).
Himanshu Aggarwal

Ale czy flip (flip (2)) nie byłby po prostu 2? 0010 1101 0010
Braden Best

Tak, będą to tylko 2. Ale ponieważ kiedy bity są przechowywane w pamięci, najbardziej znaczącym bitem było 1, co spowoduje, że liczba będzie później ujemna, jak wyjaśniono w odpowiedzi powyżej.
Himanshu Aggarwal

1
Z tego, co opisujesz i wszystkiego, co zbadałem, nie jest to uzupełnienie do dwóch, ale „zwykłe” uzupełnienie lub nieco NIE. W logice NOT 0 = 1i NOT 1 = 0. W systemie czterobitowym NOT 0011(3) = 1100(12 bez znaku, -4 podpis). Z tego, co rozumiem, uzupełnienie dwóch jest zdefiniowane jako (NOT n) + 1i jest używane do znalezienia ujemnego odpowiednika liczby niezależnie od liczby bitów. Tak więc 2c(5) = -5. Widzisz, teraz ma to sens. Tak długo, jak nazywasz tę operację tym, co to jest: nieco NIE.
Braden Best

4

int a = 4; System.out.println (~ a); Wynik byłby: -5

„~” dowolnej liczby całkowitej w java reprezentuje uzupełnienie 1 do liczby no. na przykład biorę ~ 4, co oznacza w reprezentacji binarnej 0100. po pierwsze, liczba całkowita wynosi cztery bajty, tj. 4 * 8 (8 bitów na 1 bajt) = 32. Więc w pamięci systemowej 4 jest reprezentowany jako 0000 0000 0000 0000 0000 0000 0000 0100 teraz ~ operator wykona uzupełnienie 1 na powyższym pliku binarnym

tzn. 1111 1111 1111 1111 1111 1111 1111 1011-> 1-to uzupełnienie najbardziej znaczący bit reprezentuje znak nie (albo - albo +), jeśli jest 1, to znak jest „-”, jeśli jest 0, to znak jest „+” zgodnie z ten nasz wynik jest liczbą ujemną, w java liczby ujemne są przechowywane w postaci uzupełnienia 2, uzyskany wynik musimy przekonwertować na uzupełnienie 2 (najpierw wykonaj uzupełnienie 1 i po prostu dodaj 1 do uzupełnienia 1). wszystkie one staną się zerami, z wyjątkiem najbardziej znaczącego bitu 1 (który jest naszym znakiem reprezentującym liczbę, co oznacza dla pozostałych 31 bitów 1111 1111 1111 1111 1111 1111 1111 1011 (uzyskany wynik ~ operatora) 1000 0000 0000 0000 0000 0000 0000 0100 (uzupełnienie 1)

1 (uzupełnienie 2)

1000 0000 0000 0000 0000 0000 0000 0101 teraz wynikiem jest -5 sprawdź ten link do wideo <[Bit mądrzy operatorzy w java] https://youtu.be/w4pJ4cGWe9Y


2

Po prostu ...........

Jako uzupełnienie 2 dowolnej liczby możemy obliczyć, odwracając wszystkie 1 na 0 i odwrotnie, niż dodajemy 1 do niego.

Tutaj N = ~ N daje wyniki - (N + 1) zawsze. Ponieważ system przechowuje dane w postaci uzupełnienia 2, co oznacza, że ​​przechowuje ~ N w ten sposób.

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

Na przykład::

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

Teraz jest punkt, z którego pochodzi Minus. Moim zdaniem przypuszczamy, że mamy 32-bitowy rejestr, co oznacza, że ​​2 ^ 31 -1 bit jest zaangażowany w działanie, a reszta to jeden bit, który zmienia się we wcześniejszym obliczeniu (uzupełnieniu) przechowywany jako bit znaku, który zwykle wynosi 1. I otrzymujemy wynik jako ~ 10 = -11.

~ (-11) = 10;

Powyższe jest prawdą, jeśli printf ("% d", ~ 0); otrzymujemy wynik: -1;

Ale printf ("% u", ~ 0) niż wynik: 4294967295 na maszynie 32-bitowej.


1

Bitowy operator dopełniacza (~) jest jednostronny operatorem .

Działa zgodnie z następującymi metodami

Najpierw konwertuje podaną liczbę dziesiętną na odpowiadającą jej wartość binarną w przypadku 2 najpierw konwertuje 2 na 0000 0010 (na 8 bitową liczbę binarną).

Następnie konwertuje wszystkie 1 w liczbie na 0, a wszystkie zera na 1; wtedy liczba zmieni się na 1111 1101.

to reprezentuje uzupełnienie 2 dla -3.

Aby znaleźć wartość bez znaku za pomocą dopełniacza, tzn. Po prostu przekonwertować 1111 1101 na dziesiętne (= 4294967293), możemy po prostu użyć% u podczas drukowania.


1

Myślę, że dla większości ludzi zamieszanie wynika z różnicy między liczbą dziesiętną a liczbą binarną ze znakiem, więc wyjaśnijmy to najpierw:

dla ludzkiego świata dziesiętnego: 01 oznacza 1, -01 oznacza -1, dla świata binarnego komputera: 101 oznacza 5, jeśli jest niepodpisany. 101 oznacza (-4 + 1), jeśli jest podpisany, gdy podpisana cyfra znajduje się w pozycji x. | x

tak więc odwrócony bit 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 zamieszanie wynika z pomieszania podpisanego wyniku (101 = -3) i wyniku niestałego (101 = 5)


1

tl; dr ~ odwraca bity. W rezultacie znak się zmienia. ~2jest liczbą ujemną ( 0b..101). Aby wydrukować liczbę ujemną, rubydrukujemy -uzupełnienie dwóch ~2:-(~~2 + 1) == -(2 + 1) == 3 . Liczby dodatnie są wyprowadzane bez zmian.

Istnieje wartość wewnętrzna i jej reprezentacja ciągu. W przypadku liczb całkowitych dodatnich w zasadzie pokrywają się:

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

Ten ostatni jest równoważny z:

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

~odwraca bity wartości wewnętrznej. 2jest 0b010. ~2jest 0b..101. Dwie kropki ( ..) reprezentują nieskończoną liczbę znaków 1. Ponieważ najbardziej znaczący bit (MSB) wyniku jest 1, wynikiem jest liczba ujemna ( (~2).negative? == true). Aby wydrukować liczbę ujemną, rubydrukowane jest -następnie uzupełnienie dwóch wartości wewnętrznej. Uzupełnienie do dwóch oblicza się, odwracając bity, a następnie dodając 1. Uzupełnieniem dwóch 0b..101jest 3. Takie jak:

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

Podsumowując, odwraca bity, co zmienia znak. Aby wydrukować liczbę ujemną, drukuje -, a następnie ~~2 + 1( ~~2 == 2).

Powodem, dla którego rubywyprowadza takie liczby ujemne, jest to, że traktuje przechowywaną wartość jako uzupełnienie wartości bezwzględnej do dwóch. Innymi słowy, przechowywane jest 0b..101. Jest to liczba ujemna i jako taka stanowi uzupełnienie pewnej wartości dwóch x. Aby znaleźć x, robi uzupełnienie dwóch 0b..101. Który jest uzupełnieniem dwóch uzupełnienia dwóch x. Który jest x(np ~(~2 + 1) + 1 == 2.).

W przypadku zastosowania ~liczby ujemnej, po prostu odwraca bity (co mimo to zmienia znak):

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

Bardziej mylące jest to ~0xffffff00 != 0xff(lub dowolna inna wartość z MSB równym 1). Załóżmy uprościć to trochę: ~0xf0 != 0x0f. To dlatego, że traktuje to 0xf0jako liczbę dodatnią. Co właściwie ma sens. Więc ~0xf0 == 0x..f0f. Wynik jest liczbą ujemną. Uzupełnieniem dwóch 0x..f0fjest 0xf1. Więc:

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

Jeśli nie chcesz zastosować operatorów bitowych do wyniku, możesz rozważyć ~jako -x - 1operator:

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

Ale jest to prawdopodobnie mało użyteczne.

Przykład Załóżmy, że masz 8-bitową (dla uproszczenia) maskę sieci i chcesz obliczyć liczbę 0. Możesz je obliczyć, odwracając bity i wywołując bit_length( 0x0f.bit_length == 4). Ale ~0xf0 == 0x..f0fmusimy odciąć niepotrzebne fragmenty:

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

Lub możesz użyć operatora XOR ( ^):

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

0

Najpierw musimy podzielić daną cyfrę na cyfry binarne, a następnie odwrócić ją, dodając ostatnią cyfrę binarną. Po tym wykonaniu musimy podać znak przeciwny do poprzedniej cyfry, który jest zgodny ~ 2 = -3 Wyjaśnienie : Forma binarna 2s to 00000010 zmienia się na 11111101 to jest ich uzupełnienie, a następnie jest spełniona 00000010 + 1 = 00000011, która jest binarną formą trzech i -sign Tj, -3


0

Bit-mądry operator jest jednoargumentowym operatorem, który działa według metody znaku i wielkości, zgodnie z moim doświadczeniem i wiedzą.

Na przykład ~ 2 spowoduje -3.

Wynika to z faktu, że bitowy operator najpierw reprezentowałby liczbę w znaku i wielkość, która wynosi 0000 0010 (operator 8 bitów), gdzie MSB jest bitem znaku.

Później przyjmie liczbę ujemną 2, która wynosi -2.

-2 jest reprezentowane jako 1000 0010 (operator 8 bitów) w znaku i wielkości.

Później dodaje 1 do LSB (1000 0010 + 1), co daje 1000 0011.

Który wynosi -3.


0

JavaScript tylda (~) wymusza podaną wartość na uzupełnienie jednego - wszystkie bity są odwrócone. To wszystko, co robi tylda. To nie jest znak opiniowany. Nie dodaje ani nie odejmuje żadnej ilości.

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

Na standardowych procesorach komputerowych używających języków wysokiego poziomu, takich jak JavaScript, arytmetyka podpisana w BASE10 jest najczęstsza, ale należy pamiętać, że nie jest jedyna. Bity na poziomie procesora podlegają interpretacji na podstawie wielu czynników. Na poziomie „kodu”, w tym przypadku JavaScript, są one z definicji interpretowane jako 32-bitowa liczba całkowita ze znakiem (odejdźmy od tego). Pomyśl o tym jak o kwantowej, te 32 bity reprezentują wiele możliwych wartości naraz. Zależy to całkowicie od konwertowanego obiektywu, przez który patrzysz.

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 

Wszystkie powyższe są prawdziwe jednocześnie.


0

Zasadniczo działanie jest uzupełnieniem, a nie negacją.

Tutaj x = ~ x daje wyniki - (x + 1) zawsze.

x = ~ 2

- (2 + 1)

-3

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.