この記事にはプロモーションが含まれています。
ハードウェアを触っていると、レジスタの値なりを読み解く際に2進数の表現はよく目にします。
長年整数の2進数ばかり扱っていたため、まれにレジスタの値が符号付き小数点で一瞬考え込んでしまうことがありました。
今回は符号付き固定小数点の表見について整理します。
2進数 (符号なし整数)
2進数の桁上がりが2の累乗で発生するので、例えば4bitの符号なし整数ビットの場合、各桁の重みは以下のようになります。

以降、この表現のときの10進数との間での変換手順を見ていきます。
なお、このページでは、10進数の値は数値の最後にdを、2進数の値は数値の最後にbをつけて表現します。
- 10進数 : 数値の末尾に”d”をつける
- ex. 6d
- 2進数 : 数値の末尾に”b”をつける
- ex. 0110b
変換 : 10進数 → 2進数 (符号なし整数)
10進数の数値に対して、
- 2進数の最上位桁のbitの重みで割り、商をその桁の値とする
- 上記での剰余を次の桁に送り、そのbitの重みで割り、商をその桁の値とする
(以下繰り返し)
例えば、6dを2進数に変換する場合、以下のように計算していきます。

このようにして、6d → 0110bと求まります。
変換 : 2進数 (符号なし整数) → 10進数
2進数の数値に対して、
- 各桁の数値にそのbitの重みとの積を求めて、総和を求める
例えば、0110bを10進数に変換する場合、以下のように計算していきます。

このようにして、0110b → 6dと求まります。
2進数 (符号付き整数)
符号付きの場合、最上位ビットが符号を表現し、0なら正の数、1なら負の数を表現するようになります。
それ以降のビットは、重みを表現しており、例えば4bitの符号あり整数ビットの場合、各桁の重みは以下のようになります。

また、各数値は以下のような対応関係となります。
10進数 | 2進数 (符号付き整数) |
---|---|
7d | 0111b |
6d | 0110b |
5d | 0101b |
4d | 0100b |
3d | 0011b |
2d | 0010b |
1d | 0001b |
0d | 0000b |
-1d | 1111d |
-2d | 1110b |
-3d | 1101b |
-4d | 1100b |
-5d | 1011b |
-6d | 1010b |
-7d | 1001b |
-8d | 1000b |
このように、符号付き4ビットの場合、-8d~7dの数値を表現できます。
符号なしの場合は0d~15dが表現できる数値ため、表現の範囲が変わったことが分かります。
では、10進数との変換手順がどう変わったかを以下で見ていきます。
変換 : 10進数 → 2進数 (符号付き整数)
2の補数をとる
10進数の数値に対して、
- 絶対値をとって、2進数に変換する
- 符号が
- 正のときは、最上位ビットを0にして、終了
- 負のときは、
- 最上位ビットを0にする
- 2の補数(ビット反転後に、1bを加算)をとって、終了
例えば、-6dを2進数に変換する場合、以下のように計算していきます。

この手順がもっともオーソドックスなのですが、かなりややこしいです。
マイナスのときに、2の(整数部のビット数)乗の数を足す
10進数の数値に対して、
- 符号が
- 正のときは、そのまま2進数に変換する
- 負のときは、
- 2の(整数ビット数)乗の数を加算する
- 最上位ビットを1、それ以外のビットは上記の演算結果を2進数値で埋める
こちらも同じように、-6dを2進数に変換する場合を以下に示します。

6dを1010bと変換することができました。
これは最上位ビットが-1*23のビットの重みを持っていると見立てています。

この考え方を用いると、非常に直感的に逆変換できるようになります。
具体的に、この考え方で、逆変換してみます。
変換 : 2進数 (符号付き固定小数点) → 10進数
2進数の数値に対して、最上位ビットはビットの重みがマイナスの極性を持っている見立てる
- 上記前提のもと、各桁の数値にそのbitの重みとの積を求めて、総和を求める
例えば、1010bを10進数に変換する場合、以下のように計算していきます。

2の補数を取り直しても計算できますが、この考え方の方が数値を直感的に扱えます。
これは、最上位ビットが最小値を示しており、それ以外のビットはそこからの乖離度を示しているように読み取れます。
このため、例えば、今の-6dから-4dに値を変更したいとなったら、『+2dすればいいので1100bになる』とパッと計算できます。
2進数 (符号付き固定小数点)
符号付き固定小数点ビットの場合、最上位ビットが符号を表現する点は変わりません。
その他のビットは、小数点があるため、桁下がりが発生します。
例えば4bitの符号なし整数ビットの場合、各桁の重みは以下のようになります。

10進数との変換手順はこれまで符号付き整数のときと同じですが、念のため、例示します。
各々の変換で、手順を掲載してますが、再掲です。
なお、簡単のために、2の補数をとる方法は割愛します。
変換 : 10進数 → 2進数 (符号付き固定小数点)
マイナスのときに、2の(整数部のビット数)乗の数を足す
10進数の数値に対して、
- 符号が
- 正のときは、そのまま2進数に変換する
- 負のときは、
- 2の(整数ビット数)乗の数を加算する
- 最上位ビットを1、それ以外のビットは上記の演算結果を2進数値で埋める
-4.625dを2進数に変換する場合を以下に示します。

この様にして、10110110bと求めることができました。
なお、小数点位置が分かるように、1011.0110bと記載することもあります。
変換 : 2進数 (符号付き固定小数点) → 10進数
2進数の数値に対して、最上位ビットはビットの重みがマイナスの極性を持っている見立てる
- 上記前提のもと、各桁の数値にそのbitの重みとの積を求めて、総和を求める
例えば、10110110bを10進数に変換する場合、以下のように計算していきます。

符号付き小数点の2進数も10進数に変換できました。
最上位ビットが最小値を示していると見立てた上げると、整数部だけ見て
『-8+2+1=-5なので、-5d~-4dの値なんだな』
とパッと推定できます。
まとめ
符号付き2進数表現で、最上位ビットは最小値を示しており、その他のビットはそこからの乖離度を示しているという考え方を記載しました。
この考え方は、負の値をすぐに目的の表現に変換でき、かつ、直感的に数値を扱えるため便利だと個人的には思ってます。
ただ、ネットで検索してもあまり同じ考え方を見なかったので、まとめてみました。
もし考え方に誤りがあるようでしたら、ご指摘のコメントなどいただければと思います。
また、以下のサイトでは符号付き小数点に対応したn進数変換のツールが用意されてます。
もし、変換してみたいという方は試しにアクセスしてみてください。
コメント