Si A est un entier naturel, on note ~A le nombre dont la représentation en base 2 est la même que celle de A, mais en inversant les 0 et les 1.
Par exemple, sur 8 bits, si A = 00001010, alors ~A = 11110101.
Si tu sommes A et ~A tu obtiens le nombre dont la représentation binaire n'est faite que de 1, sur n bits. Si tu rajoutes 1 à ce nombre, tu vas propager la retenue de droite à gauche, et tu vas te retrouver avec le nombre 1 suivi de n zéros. Et ça c'est la représentation binaire de , ou si tu préfères, c'est 1<<n.
Autrement dit, pour l'addition binaire.
Mais il y a encore un problème : le plus grand entier représentable sur n bits est . Pour représenter , il te faudra n+1 bits au moins !.
Mais si tu restes sur n bits, alors ton overflow sera ignoré (et le registre de flags mis à jour, mais ça ne nous intéresse pas ici). En gros, on ne va garder que les n bits de poids faible du résultat. Ce qui également revient à faire toutes tes opérations modulo . En particulier est congru à 0 modulo et donc
modulo / dans / pour l'addition binaire sur bits (tout ça c'est pareil) : A + (~A) + 1 = 0.
Ensuite, on fait jouer l'associativité de l'addition. On cherche un B tel que A + B = 0 comme opposé à droite de A modulo . B = (~A) + 1 convient, et il est unique.
C'est aussi l'opposé à gauche, parce que notre addition est commutative.
Tu peux vérifier si tu veux que 1 + ~(1 + ~A). Donc en notant B = -A, on a bien -(-A) = A.