整数の符号反転演算(-x=~x+1)

<code>-x = 0 - x</code> ですが、最近では見かけなくなった <code>-x = ~x + 1</code> の詳細を再確認する。

# 符号反転 : -x = ~x + 1

符号付き整数 <code>x</code> の符号反転 <code>-x</code> に違和感はないでしょう。

符号なし整数 <code>x</code> の符号反転 <code>-x</code> では、分かっていても「負になった値は何処へ？」という疑問が湧きます。

最近の CPU の仕様書では見かけなくなりましたが、古めの仕様書にある符号反転命令(<code>neg</code>)は

- 全ビット反転(<code>not</code>)後に 1 を加える ( <code>~x + 1</code> )
  - <sub>符号あり/なし共通</sub>

となっていて、符号なしで考えた方がしっくりきます。

例として、整数を 4 ビット幅で考えます。符号の有無と数値は次の表になります。

| 符号 | なし | | 符号 | あり |
|:-:|--:|:-:|:-:|--:|
| <code>0000</code> | <code> 0</code> | | <code>1000</code> | <code>-8</code> |
| <code>0001</code> | <code> 1</code> | | <code>1001</code> | <code>-7</code> |
| <code>0010</code> | <code> 2</code> | | <code>1010</code> | <code>-6</code> |
| <code>0011</code> | <code> 3</code> | | <code>1011</code> | <code>-5</code> |
| <code>0100</code> | <code> 4</code> | | <code>1100</code> | <code>-4</code> |
| <code>0101</code> | <code> 5</code> | | <code>1101</code> | <code>-3</code> |
| <code>0110</code> | <code> 6</code> | | <code>1110</code> | <code>-2</code> |
| <code>0111</code> | <code> 7</code> | | <code>1111</code> | <code>-1</code> |
| <code>1000</code> | <code> 8</code> | | <code>0000</code> | <code> 0</code> |
| <code>1001</code> | <code> 9</code> | | <code>0001</code> | <code> 1</code> |
| <code>1010</code> | <code>10</code> | | <code>0010</code> | <code> 2</code> |
| <code>1011</code> | <code>11</code> | | <code>0011</code> | <code> 3</code> |
| <code>1100</code> | <code>12</code> | | <code>0100</code> | <code> 4</code> |
| <code>1101</code> | <code>13</code> | | <code>0101</code> | <code> 5</code> |
| <code>1110</code> | <code>14</code> | | <code>0110</code> | <code> 6</code> |
| <code>1111</code> | <code>15</code> | | <code>0111</code> | <code> 7</code> |


# 符号反転 : neg = not + 1

上のビットから順に反転(xor)して最後に<code>+1</code>するときの整数値の変化を確認します。

**符号なし**

| 反転, 加算 | 数値 |
|:--|:--|
| <code>0000<sub>(2)</sub>, 0</code> | <code>&nbsp;0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15</code> |
| <code>1000<sub>(2)</sub>, 0</code> | <code>&nbsp;8, 9,10,11,12,13,14,15, 0, 1, 2, 3, 4, 5, 6, 7</code> |
| <code>1100<sub>(2)</sub>, 0</code> | <code>12,13,14,15, 8, 9,10,11, 4, 5, 6, 7, 0, 1, 2, 3</code> |
| <code>1110<sub>(2)</sub>, 0</code> | <code>14,15,12,13,10,11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1</code> |
| <code>1111<sub>(2)</sub>, 0</code> | <code>15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0</code> |
| <code>1111<sub>(2)</sub>, 1</code> | <code>&nbsp;0,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1</code> |

**符号あり**

| 反転, 加算 | 数値 |
|:-:|:--|
| <code>0000<sub>(2)</sub>, 0</code> | <code>-8,-7,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6, 7</code> |
| <code>1000<sub>(2)</sub>, 0</code> | <code>&nbsp;0, 1, 2, 3, 4, 5, 6, 7,-8,-7,-6,-5,-4,-3,-2,-1</code> |
| <code>1100<sub>(2)</sub>, 0</code> | <code>&nbsp;4, 5, 6, 7, 0, 1, 2, 3,-4,-3,-2,-1,-8,-7,-6,-5</code> |
| <code>1110<sub>(2)</sub>, 0</code> | <code>&nbsp;6, 7, 4, 5, 2, 3, 0, 1,-2,-1,-4,-3,-6,-5,-8,-7</code> |
| <code>1111<sub>(2)</sub>, 0</code> | <code>&nbsp;7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7,-8</code> |
| <code>1111<sub>(2)</sub>, 1</code> | <code>-8, 7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7</code> |

**元値と結果の比較**

| 元値 | 符号<br>なし | 符号<br>あり | 結果 | 符号<br>なし | 符号<br>あり |
|:-:|--:|--:|:-:|--:|--:|
| <code>0000</code> | <code> 0</code> | <code> 0</code> | <code>0000</code> | <code> 0</code> | <code> 0</code> |
| <code>0001</code> | <code> 1</code> | <code> 1</code> | <code>1111</code> | <code>15</code> | <code>-1</code> |
| <code>0010</code> | <code> 2</code> | <code> 2</code> | <code>1110</code> | <code>14</code> | <code>-2</code> |
| <code>0011</code> | <code> 3</code> | <code> 3</code> | <code>1101</code> | <code>13</code> | <code>-3</code> |
| <code>0100</code> | <code> 4</code> | <code> 4</code> | <code>1100</code> | <code>12</code> | <code>-4</code> |
| <code>0101</code> | <code> 5</code> | <code> 5</code> | <code>1011</code> | <code>11</code> | <code>-5</code> |
| <code>0110</code> | <code> 6</code> | <code> 6</code> | <code>1010</code> | <code>10</code> | <code>-6</code> |
| <code>0111</code> | <code> 7</code> | <code> 7</code> | <code>1001</code> | <code> 9</code> | <code>-7</code> |
| <code>1000</code> | <code> 8</code> | <code>-8</code> | <code>1000</code> | <code> 8</code> | <code>-8</code> |
| <code>1001</code> | <code> 9</code> | <code>-7</code> | <code>0111</code> | <code> 7</code> | <code> 7</code> |
| <code>1010</code> | <code>10</code> | <code>-6</code> | <code>0110</code> | <code> 6</code> | <code> 6</code> |
| <code>1011</code> | <code>11</code> | <code>-5</code> | <code>0101</code> | <code> 5</code> | <code> 5</code> |
| <code>1100</code> | <code>12</code> | <code>-4</code> | <code>0100</code> | <code> 4</code> | <code> 4</code> |
| <code>1101</code> | <code>13</code> | <code>-3</code> | <code>0011</code> | <code> 3</code> | <code> 3</code> |
| <code>1110</code> | <code>14</code> | <code>-2</code> | <code>0010</code> | <code> 2</code> | <code> 2</code> |
| <code>1111</code> | <code>15</code> | <code>-1</code> | <code>0001</code> | <code> 1</code> | <code> 1</code> |

# 実行例

```python:Python
>>> [~x+1 for x in range(-4,4)]
[4, 3, 2, 1, 0, -1, -2, -3]
```

```JavaScript: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
]
```

こんな方法を使う方はいないと思いますが、使用可能な数値範囲は注意してください。

---

記事を書いている途中で彼是思い出しました。記事は同じ情報を上書きするメモリ・リ...