-x = 0 - x
ですが、最近では見かけなくなった -x = ~x + 1
の詳細を再確認する。
符号反転 : -x = ~x + 1
符号付き整数 x
の符号反転 -x
に違和感はないでしょう。
符号なし整数 x
の符号反転 -x
では、分かっていても「負になった値は何処へ?」という疑問が湧きます。
最近の CPU の仕様書では見かけなくなりましたが、古めの仕様書にある符号反転命令(neg
)は
- 全ビット反転(
not
)後に 1 を加える (~x + 1
)- 符号あり/なし共通
となっていて、符号なしで考えた方がしっくりきます。
例として、整数を 4 ビット幅で考えます。符号の有無と数値は次の表になります。
符号 | なし | 符号 | あり | |
---|---|---|---|---|
0000 |
0 |
1000 |
-8 |
|
0001 |
1 |
1001 |
-7 |
|
0010 |
2 |
1010 |
-6 |
|
0011 |
3 |
1011 |
-5 |
|
0100 |
4 |
1100 |
-4 |
|
0101 |
5 |
1101 |
-3 |
|
0110 |
6 |
1110 |
-2 |
|
0111 |
7 |
1111 |
-1 |
|
1000 |
8 |
0000 |
0 |
|
1001 |
9 |
0001 |
1 |
|
1010 |
10 |
0010 |
2 |
|
1011 |
11 |
0011 |
3 |
|
1100 |
12 |
0100 |
4 |
|
1101 |
13 |
0101 |
5 |
|
1110 |
14 |
0110 |
6 |
|
1111 |
15 |
0111 |
7 |
符号反転 : neg = not + 1
上のビットから順に反転(xor)して最後に+1
するときの整数値の変化を確認します。
符号なし
反転, 加算 | 数値 |
---|---|
0000(2), 0 |
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 |
1000(2), 0 |
8, 9,10,11,12,13,14,15, 0, 1, 2, 3, 4, 5, 6, 7 |
1100(2), 0 |
12,13,14,15, 8, 9,10,11, 4, 5, 6, 7, 0, 1, 2, 3 |
1110(2), 0 |
14,15,12,13,10,11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1 |
1111(2), 0 |
15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 |
1111(2), 1 |
0,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1 |
符号あり
反転, 加算 | 数値 |
---|---|
0000(2), 0 |
-8,-7,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6, 7 |
1000(2), 0 |
0, 1, 2, 3, 4, 5, 6, 7,-8,-7,-6,-5,-4,-3,-2,-1 |
1100(2), 0 |
4, 5, 6, 7, 0, 1, 2, 3,-4,-3,-2,-1,-8,-7,-6,-5 |
1110(2), 0 |
6, 7, 4, 5, 2, 3, 0, 1,-2,-1,-4,-3,-6,-5,-8,-7 |
1111(2), 0 |
7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7,-8 |
1111(2), 1 |
-8, 7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7 |
元値と結果の比較
元値 | 符号 なし |
符号 あり |
結果 | 符号 なし |
符号 あり |
---|---|---|---|---|---|
0000 |
0 |
0 |
0000 |
0 |
0 |
0001 |
1 |
1 |
1111 |
15 |
-1 |
0010 |
2 |
2 |
1110 |
14 |
-2 |
0011 |
3 |
3 |
1101 |
13 |
-3 |
0100 |
4 |
4 |
1100 |
12 |
-4 |
0101 |
5 |
5 |
1011 |
11 |
-5 |
0110 |
6 |
6 |
1010 |
10 |
-6 |
0111 |
7 |
7 |
1001 |
9 |
-7 |
1000 |
8 |
-8 |
1000 |
8 |
-8 |
1001 |
9 |
-7 |
0111 |
7 |
7 |
1010 |
10 |
-6 |
0110 |
6 |
6 |
1011 |
11 |
-5 |
0101 |
5 |
5 |
1100 |
12 |
-4 |
0100 |
4 |
4 |
1101 |
13 |
-3 |
0011 |
3 |
3 |
1110 |
14 |
-2 |
0010 |
2 |
2 |
1111 |
15 |
-1 |
0001 |
1 |
1 |
実行例
Python
>>> [~x+1 for x in range(-4,4)]
[4, 3, 2, 1, 0, -1, -2, -3]
JavaScript
> [...Array(8).keys()].map(x=>x-4)
[
-4, -3, -2, -1,
0, 1, 2, 3
]
> [...Array(8).keys()].map(x=>x-4).map(x=>~x+1)
[
4, 3, 2, 1,
0, -1, -2, -3
]
こんな方法を使う方はいないと思いますが、使用可能な数値範囲は注意してください。
記事を書いている途中で彼是思い出しました。記事は同じ情報を上書きするメモリ・リ...