Odpowiedzi:
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.
~
odwraca bity wartości.
Dlaczego ~2
to -3
ma 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.
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 -3
liczbie, do której 3
należ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 1101
jest -3
, odwracanie bitów dostaniesz 0010
który wynosi dwa.
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 2
jest reprezentowana 0000 0010
w 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.
add, flip, add
. 0010
-> 0011
-> 1100
->1101
0010
1101
0010
NOT 0 = 1
i 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) + 1
i 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.
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)
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
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.
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.
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)
tl; dr ~
odwraca bity. W rezultacie znak się zmienia. ~2
jest liczbą ujemną ( 0b..101
). Aby wydrukować liczbę ujemną, ruby
drukujemy -
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. 2
jest 0b010
. ~2
jest 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ą, ruby
drukowane 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..101
jest 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 ruby
wyprowadza 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 0xf0
jako liczbę dodatnią. Co właściwie ma sens. Więc ~0xf0 == 0x..f0f
. Wynik jest liczbą ujemną. Uzupełnieniem dwóch 0x..f0f
jest 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 - 1
operator:
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..f0f
musimy 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"
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
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.
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.