プログラミングを始めたばかりのころ、マイナスの数は2の補数で計算しますよー。
たとえば8bitの場合、41
00101001
のマイナスの数(-41)は、反転して1を足しますよー。
要は、
11010110
に1を足して、
11010111
ってやれば、-41になりますよー。と本に書いてあって、それを覚えました。
情報処理試験とかでも出るんですかね?
なぜ?
と思ったものですが、なぜを説明している本はないんですね。残念ながら。
なので、簡単に説明したいと思います。
理解するには前提が二つあります。
前提1.
マイナスの数とは、元の数と足し合わせるとゼロになる数(足し算の逆元)ということで良いですよね?
41 + (-41) = 0
このような感じです。当たり前ですね。
前提2.
8 bit の整数において足し算は、普通に使っている足し算と定義が違います。
仮に、この 8 bit 整数における足し算の記号を ++ と定義するなら、
a ++ b = (a + b) % 256
となります。
256になった場合は、桁があふれてしまうので、それを無視するわけです。
ここで、反転する(not)の性質を見てみると、
00101001
+)11010110
11111111
といった感じで、必ず255(11111111)になります。
さらにこれに 1 を足すと 256 になるわけですが、前提2からこれは 0 になります。
ということで、
a ++ not(a) ++ 1 = 0
なわけです。直観的に、結合側は成り立ちそうなので、
a ++ (not(a) ++ 1) = 0
と言い換えられます。
元の数と2の補数を足すと必ず 0 になります。
ということは前提1を考えれば、
2の補数は元の数のマイナスの数である
と言えそうです。
というわけで、なんとなく謎の計算を覚えさせられていたわけですが、理由はとっても単純で当たり前の結果だったりします。
補足
ここでは、数をどのように2進数で表現するか(符号化)については言及していません。
たとえば 10000000 を 128 と解釈するのか、 -127 と解釈するのか、などですね。
何の前提もなくマイナスの数と言っていますが、正確に言うなら2進数の加算の逆元は2の補数で計算できますという話でしかないですね。