~ x + ~ y == ~ (x + y) è sempre falso?


153

Questo codice viene sempre valutato come falso? Entrambe le variabili sono ints firmati a complemento di due.

~x + ~y == ~(x + y)

Sento che dovrebbe esserci un numero che soddisfi le condizioni. Ho provato a testare i numeri tra -5000e 5000non ho mai raggiunto l'uguaglianza. C'è un modo per impostare un'equazione per trovare le soluzioni alla condizione?

Sostituire l'uno con l'altro causerà un bug insidioso nel mio programma?


6
Vuoi una prova o qualcosa del genere?
Alvin Wong,

26
Tenere presente che nei casi di overflow di numeri interi con segno, si tratta di un comportamento tecnicamente indefinito. Quindi è possibile che ritorni trueanche se non possono mai assumere un complemento rigoroso per due.
Mistico il

1
@AlvinWong sì, una spiegazione sarebbe gradita
Steve

1
@Steve: potresti dimostrare di aver provato tutti i soliti sospetti (-1, 0, 1, 2 e così via) in tutte le combinazioni, nonché i tuoi tentativi di "risolvere" il problema per parole di piccole dimensioni ( tre bit? quattro bit?). Ciò contribuirebbe sicuramente a convincerci che non stiamo solo aiutando qualcuno a ottenere qualcosa che prima non hanno provato a guadagnare da soli. :)
sarnold,

4
@AlexLockwood Quando ho pubblicato la domanda per la prima volta, ho pensato che contrassegnare la domanda come "compiti a casa" chiedesse alle persone di fornire indizi per aiutarmi a risolvere il problema (come afferma la descrizione del tag "compiti a casa") e non solo dare risposte. Ecco perché ho semplicemente posto la domanda del problema :)
Steve,

Risposte:


237

Supponiamo per amor di contraddizione che esistano alcuni xe alcuni y(mod 2 n ) tali che

~(x+y) == ~x + ~y

Dal complemento a due *, sappiamo che,

      -x == ~x + 1
<==>  -1 == ~x + x

Notando questo risultato, abbiamo,

      ~(x+y) == ~x + ~y
<==>  ~(x+y) + (x+y) == ~x + ~y + (x+y)
<==>  ~(x+y) + (x+y) == (~x + x) + (~y + y)
<==>  ~(x+y) + (x+y) == -1 + -1
<==>  ~(x+y) + (x+y) == -2
<==>  -1 == -2

Quindi, una contraddizione. Pertanto, ~(x+y) != ~x + ~yper tutti xe y(mod 2 n ).


* È interessante notare che su una macchina con l'aritmetica del proprio complemento, l'uguaglianza è vera per tutti xe y. Questo perché sotto lo stesso complemento, ~x = -x. Così, ~x + ~y == -x + -y == -(x+y) == ~(x+y).


47
Naturalmente, C non richiede questo comportamento; in quanto non richiede la rappresentazione del complemento a due.
Billy ONeal,

12
A proposito, l'uguaglianza è vera per il proprio complemento. L'operazione NOT non è realmente definita per il numero in generale, quindi la miscelazione di NOT con l'aggiunta comporta un comportamento diverso a seconda della rappresentazione del numero.
nhahtdh,

9
Si potrebbe semplicemente riaffermare il problema per gli interi senza segno e quindi il complemento a due non entra affatto in gioco.
R .. GitHub smette di aiutare ICE il

5
Ancora più semplice, IMHO ~x == -(x+1)~(x+y) == ~x + ~y-(x+y+1) == -(x+1) + -(y+1)-1 == -2
:,

7
@BillyONeal, non ti preoccupare, stavo solo scherzando e apprezzo che tu l'abbia menzionato :). Ti offro da bere il giorno in cui incontro una macchina che esegue l'aritmetica del complemento ... come suona? haha
Alex Lockwood,

113

Complemento a due

Nella stragrande maggioranza dei computer, se xè un numero intero, -xviene rappresentato come ~x + 1. Equivalentemente, ~x == -(x + 1). Fare questa sostituzione nella tua equazione dà:

  • ~ x + ~ y == ~ (x + y)
  • - (x + 1) + - (y + 1) = - ((x + y) + 1)
  • -x - y - 2 = -x - y - 1
  • -2 = -1

che è una contraddizione, quindi ~x + ~y == ~(x + y)è sempre falso .


Detto questo, i pedanti indicheranno che C non richiede il complemento di due, quindi dobbiamo anche considerare ...

Un complemento

Nel proprio complemento , -xè semplicemente rappresentato come ~x. Lo zero è un caso speciale, con entrambe le rappresentazioni di tutti-0 ( +0) e tutti-1 ( -0), ma IIRC, C richiede +0 == -0anche se hanno modelli di bit diversi, quindi questo non dovrebbe essere un problema. Basta sostituire ~con -.

  • ~ x + ~ y == ~ (x + y)
  • -x + (-y) = - (x + y)

che è vero per tutti xe y.


13
+1 per una risposta che in realtà considera sia il complemento a due che il complemento su un piano di parità.
un CVn del

13
@ dan04, +0 == -0. Finalmente qualcosa che ha senso in C. :)
Alex Lockwood,

32

Considera solo il bit più a destra di entrambi xe y(IE. Se x == 13che è 1101nella base 2, vedremo solo l'ultimo bit, a 1) Quindi ci sono quattro casi possibili:

x = 0, y = 0:

LHS: ~ 0 + ~ 0 => 1 + 1 => 10
RHS: ~ (0 + 0) => ~ 0 => 1

x = 0, y = 1:

LHS: ~ 0 + ~ 1 => 1 + 0 => 1
RHS: ~ (0 + 1) => ~ 1 => 0

x = 1, y = 0:

Lo lascerò a te dato che si tratta di compiti a casa (suggerimento: è lo stesso del precedente con x e y scambiati).

x = 1, y = 1:

Lascio questo anche a te.

Puoi mostrare che il bit più a destra sarà sempre diverso sul lato sinistro e sul lato destro dell'equazione dato qualsiasi input possibile, quindi hai dimostrato che entrambi i lati non sono uguali, poiché hanno almeno quel bit che viene capovolto l'uno dall'altro.


27

Se il numero di bit è n

~x = (2^n - 1) - x
~y = (2^n - 1) - y


~x + ~y = (2^n - 1) +(2^n - 1) - x - y =>  (2^n + (2^n - 1) - x - y ) - 1 => modulo: (2^n - 1) - x - y - 1.

Adesso,

 ~(x + y) = (2^n - 1) - (x + y) = (2^n - 1) - x - y.

Quindi, saranno sempre disuguali, con una differenza di 1.


4
@nhahtdh e come si definisce l' ~operazione su numeri di larghezza non fissa?
hamstergene,

1
Ho dato questa risposta con questo numero di bit in modo che sia facile correlare con ciò che viene insegnato in classe. Si noti che ~ x dipende fortemente dal numero di bit, n, utilizzato per rappresentare il numero. Quindi è sensato attenersi a uno, quando si tenta di verificarlo sperimentalmente.
Karthik Kumar Viswanathan,

1
@hamstergene: so che il numero di bit è fisso, ma il mio punto è che non deve essere tale importo (8, 16, ecc.).
nhahtdh,

1
Questi sono valori per i quali è facile scrivere un programma per verificare la risposta. Funziona con qualsiasi n, purché ~ x e ~ y siano scritti in modo da corrispondere a quello indicato.
Karthik Kumar Viswanathan,

1
@hamstergene: non ho problemi con la prova, solo che i numeri danno la falsa implicazione che funziona solo per quei casi.
nhahtdh,

27

Suggerimento:

x + ~x = -1(mod 2 n )

Supponendo che l'obiettivo della domanda sia testare la tua matematica (piuttosto che le tue abilità di lettura delle specifiche C), questo dovrebbe portarti alla risposta.


2
Solo su macchine a complemento a due. (Lo standard C non lo richiede)
Billy ONeal

12
@Billy: È come dire "solo per persone a due braccia".
dan04,

2
@ dan04: No, non lo è. Mi piacerebbe dire che tutta la grandezza firmata e quelle rappresentazioni complementari erano sparite dal mondo. Ma mi sbaglierei nel dirlo. Lo standard C non ti consente di fare questo presupposto; quindi direi il codice che rende tale presupposto un codice errato la maggior parte delle volte. (Soprattutto quando di solito ci sono modi migliori per scherzare con i numeri firmati rispetto ai bit twiddling; e in particolare quando i numeri senza segno sono probabilmente una scelta migliore la maggior parte delle volte comunque)
Billy ONeal

10

Sia nel complemento a uno che a due (e anche nei 42), questo può essere dimostrato:

~x + ~y == ~(x + a) + ~(y - a)

Ora lascia a = ye abbiamo:

~x + ~y == ~(x + y) + ~(y - y)

o:

~x + ~y == ~(x + y) + ~0

Pertanto, nel complemento a due ~0 = -1, la proposizione è falsa.

Nel complemento di ciò ~0 = 0, la proposizione è vera.


7

Secondo il libro di Dennis Ritchie, C non implementa il complemento a due per impostazione predefinita. Pertanto, la tua domanda potrebbe non essere sempre vera.


5

Lasciare MAX_INTessere l'int rappresentato da 011111...111(per quanti bit ci siano). Allora lo sai ~x + x = MAX_INTe ~y + y = MAX_INT, quindi, saprai per certo che la differenza tra ~x + ~ye ~(x + y)è 1.


5

C non richiede che il complemento a due sia ciò che viene implementato. Tuttavia, per numeri interi senza segno vengono applicate logiche simili. Le differenze saranno sempre 1 in questa logica!


3

Naturalmente, C non richiede questo comportamento perché non richiede la rappresentazione del complemento di due. Ad esempio, ~x = (2^n - 1) - xe ~y = (2^n - 1) - yotterrà questo risultato.


0

Ah, matematica discreta fondamentale!

Dai un'occhiata alla legge di De Morgan

~x & ~y == ~(x | y)

~x | ~y == ~(x & y)

Molto importante per le prove booleane!


Semplicemente sbagliato. In C + è aggiunta, * moltiplicazione e non booleana o o e.
nalply,

Grazie per aver segnalato gli operatori errati, in ogni caso. Ora è stato aggiornato con gli operatori corretti, sebbene tu abbia ragione in quanto non si applica alla domanda originale.
David Kaczynski,

1
Bene, se vero è uno e falso è zero, allora + e * si comportano esattamente come oe e, inoltre, il complemento di due si comporta come no, quindi la legge si applica comunque.
a1an

Grazie per averlo sottolineato, a1an. Stavo cercando di pensare a come le leggi di De Morgan potessero ancora essere applicabili alla domanda originale, ma sono passati diversi anni da quando ho studiato la programmazione in C o la matematica discreta.
David Kaczynski,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.