Czy ten kod zawsze daje wynik fałszywy? Obie zmienne są liczbami int ze znakiem uzupełnienia do dwóch.
~x + ~y == ~(x + y)
Wydaje mi się, że powinna istnieć liczba spełniająca warunki. Próbowałem sprawdzić liczby pomiędzy -5000
i, 5000
ale nigdy nie osiągnąłem równości. Czy istnieje sposób na utworzenie równania, aby znaleźć rozwiązania warunku?
Czy zamiana jednego na drugi spowoduje podstępny błąd w moim programie?
true
nawet jeśli nigdy nie będą mogli przyjąć ścisłego dopełnienia do dwóch.Odpowiedzi:
Załóżmy dla sprzeczności, że istnieją takie,
x
a niektórey
(mod 2 n ) takieDzięki dopełnieniu do dwóch * wiemy, że
Uwzględniając ten wynik,
Stąd sprzeczność. Dlatego
~(x+y) != ~x + ~y
dla wszystkichx
iy
(mod 2 n ).* Warto zauważyć, że na maszynie z własną arytmetyką dopełnień równość faktycznie obowiązuje dla wszystkich
x
iy
. To dlatego, że pod jednym z dopełnieniem,~x = -x
. Zatem~x + ~y == -x + -y == -(x+y) == ~(x+y)
.źródło
~x == -(x+1)
tak~(x+y) == ~x + ~y
implikuje-(x+y+1) == -(x+1) + -(y+1)
implikuje-1 == -2
Dopełnienie do dwóch
W zdecydowanej większości komputerów, jeśli
x
jest liczbą całkowitą, to-x
jest reprezentowane~x + 1
. Równoważnie~x == -(x + 1)
. Dokonanie tego podstawienia w swoim równaniu daje:co jest sprzecznością, więc
~x + ~y == ~(x + y)
zawsze jest fałszywe .To powiedziawszy, pedanci zwrócą uwagę, że C nie wymaga uzupełnienia do dwóch, więc musimy również rozważyć ...
Dopełnienie
W kod uzupełnień do jedności ,
-x
jest po prostu reprezentowane~x
. Zero jest przypadkiem specjalnym, mając zarówno reprezentacje all-0 (+0
), jak i all-1 (-0
), ale IIRC, C wymaga,+0 == -0
nawet jeśli mają różne wzorce bitowe, więc nie powinno to stanowić problemu. Wystarczy podstawić~
z-
.co jest prawdą dla wszystkich
x
iy
.źródło
+0 == -0
. Wreszcie coś, co ma sens w C. :)Rozważmy tylko skrajny prawy bit z obu
x
iy
(tj. Jeślix == 13
który jest1101
w bazie 2, przyjrzymy się tylko ostatniemu bitowi, a1
) Istnieją cztery możliwe przypadki:x = 0, y = 0:
x = 0, y = 1:
x = 1, y = 0:
x = 1, y = 1:
Możesz pokazać, że najbardziej prawy bit będzie zawsze różny po lewej i prawej stronie równania, biorąc pod uwagę wszelkie możliwe dane wejściowe, więc udowodniłeś, że obie strony nie są równe, ponieważ mają co najmniej ten jeden odwrócony bit od siebie nawzajem.
źródło
Jeśli liczba bitów wynosi n
Teraz,
Dlatego zawsze będą nierówne, z różnicą 1.
źródło
~
operację na liczbach o stałej szerokości?Wskazówka:
x + ~x = -1
(mod 2 n )Zakładając, że celem pytania jest sprawdzenie Twojej matematyki (a nie umiejętności czytania specyfikacji C), powinno to doprowadzić Cię do odpowiedzi.
źródło
W dopełnieniu zarówno jednym, jak i dwóch (a nawet w 42-ach) można to udowodnić:
Teraz pozwól
a = y
i mamy:lub:
Dlatego w uzupełnieniu do dwóch
~0 = -1
, to zdanie jest fałszywe.W uzupełnieniu
~0 = 0
, twierdzenie to jest prawdziwe.źródło
Według książki Dennisa Ritchiego, C nie implementuje domyślnie dopełnienia do dwóch. Dlatego twoje pytanie może nie zawsze być prawdziwe.
źródło
Niech
MAX_INT
będzie wartością int reprezentowaną przez011111...111
(dla dowolnej liczby bitów). Wtedy to wiesz~x + x = MAX_INT
i~y + y = MAX_INT
dlatego będziesz wiedział na pewno, że różnica między~x + ~y
a~(x + y)
jest1
.źródło
C nie wymaga implementacji dopełnienia do dwóch. Jednak w przypadku liczb całkowitych bez znaku stosowane są podobne logiki. W tej logice różnice zawsze będą wynosić 1!
źródło
Oczywiście C nie wymaga takiego zachowania, ponieważ nie wymaga reprezentacji dopełnienia do dwóch. Na przykład
~x = (2^n - 1) - x
&~y = (2^n - 1) - y
otrzyma ten wynik.źródło
Ach, podstawowa matematyka dyskretna!
Sprawdź prawo De Morgana
Bardzo ważne dla dowodów logicznych!
źródło