16進数の整数部分の扱いに慣れてきたら、次は「小数点以下の表現」についても理解を深めることが重要です。
16進数で小数を表現する方法は整数部分とは少し異なり、固定小数点表現や浮動小数点表現といった仕組みが登場します。
プログラミングや数値計算の分野では、小数の精度や丸め誤差の問題を理解するためにも、16進数の小数点表記の知識が役立ちます。
本記事では、16進数の小数点表記の仕組み・変換手順・固定小数点・浮動小数点の概念まで詳しく解説していきます。
16進数の小数点表記の基本的な仕組み
それではまず、16進数の小数点表記の基本的な仕組みについて解説していきます。
16進数でも整数と同様に小数点(ピリオド)を使って小数部分を表現できます。
整数部分は右に行くほど16の正のべき乗(16^0・16^1……)の重みを持ちましたが、小数点以下の桁は右に行くほど16の負のべき乗(16^-1・16^-2……)の重みを持ちます。
16進数の小数点以下の各桁の重み
小数点直後(1桁目):16^(-1) = 1/16 ≒ 0.0625
2桁目:16^(-2) = 1/256 ≒ 0.00390625
3桁目:16^(-3) = 1/4096 ≒ 0.000244140625
4桁目:16^(-4) = 1/65536 ≒ 0.0000152587890625
この重みを使って、16進数の小数を10進数に変換することができます。
小数部分の変換は整数部分の逆の発想で行うため、慣れるまで少し時間がかかるかもしれませんが、仕組みを理解すれば正確に変換できるでしょう。
16進数の小数を10進数に変換する手順
具体例で16進数の小数を10進数に変換する手順を確認します。
16進数「A.8」を10進数に変換する
整数部分:A = 10 × 16^0 = 10
小数部分:8 × 16^(-1) = 8 × (1/16) = 8/16 = 0.5
合計:10 + 0.5 = 10.5
答え:16進数「A.8」= 10進数「10.5」
16進数「1.4」を10進数に変換する
整数部分:1 × 16^0 = 1
小数部分:4 × 16^(-1) = 4/16 = 0.25
合計:1 + 0.25 = 1.25
答え:16進数「1.4」= 10進数「1.25」
「0.8(16進数)=0.5(10進数)」「0.4(16進数)=0.25(10進数)」という対応は頻繁に出てくるため覚えておくと便利でしょう。
10進数の小数を16進数に変換する手順
10進数の小数を16進数に変換する手順は、整数部分と小数部分を分けて処理します。
10進数「13.75」を16進数に変換する
整数部分:13 → 16進数「D」
小数部分の変換手順(×16を繰り返す):
0.75 × 16 = 12.0 → 整数部分「12」=「C」、残り0.0
残りが0になったので終了
答え:10進数「13.75」= 16進数「D.C」
小数部分の変換は「小数部分に16を掛け、整数部分を取り出す」という操作を、残りの小数部分が0になるまで繰り返すという手順です。
10進数で0.1のような値は、16進数(および2進数)では無限に続く循環小数となる場合があるため、変換が終わらない場合は桁数を決めて打ち切る必要があるでしょう。
固定小数点表現と16進数
続いては、固定小数点表現と16進数の関係を確認していきます。
コンピューターで小数を扱う方法として「固定小数点表現」と「浮動小数点表現」の2種類があります。
固定小数点表現の仕組み
固定小数点表現とは、小数点の位置をあらかじめ固定して数値を表現する方式のことです。
たとえば16ビットのデータを「上位8ビット=整数部・下位8ビット=小数部」と決めた場合、0x0180は整数部「01」(1)・小数部「80」(0.5)として「1.5」を表します。
固定小数点表現はシンプルな回路で実装できるため、組み込みシステムや信号処理プロセッサでよく使われます。
表現できる数値の範囲と精度が固定されてしまうという制約がありますが、計算コストが低いという利点があるでしょう。
浮動小数点表現(IEEE 754)と16進数
現代のコンピューターで最も広く使われている小数の表現方式が「浮動小数点表現」です。
IEEE 754規格の32ビット単精度浮動小数点数は「符号1ビット・指数部8ビット・仮数部23ビット」で構成されており、16進数8桁で表現できます。
たとえば「1.0」はIEEE 754の32ビット浮動小数点では「3F800000」(16進数)となります。
プログラミングにおける丸め誤差(0.1+0.2≠0.3になる問題)は、10進数の小数が2進数(および16進数)で正確に表現できないことに起因しているのです。
| 値(10進数) | IEEE 754(16進数) | 実際の2進数値 |
|---|---|---|
| 1.0 | 3F800000 | 1.0(正確) |
| 0.5 | 3F000000 | 0.5(正確) |
| 0.1 | 3DCCCCCD | 0.100000001…(近似) |
| 0.25 | 3E800000 | 0.25(正確) |
精度と丸め誤差の問題
続いては、16進数・浮動小数点における精度と丸め誤差の問題を確認していきます。
プログラミングで小数を扱う際に必ず理解しておきたいのが精度と丸め誤差の問題です。
2進数で正確に表現できない10進数の小数
10進数で「0.1」や「0.3」のような値は、2進数(および16進数)では無限に続く小数となります。
コンピューターの浮動小数点数は有限のビット数で近似値として格納するため、わずかな誤差が生じます。
この誤差が積み重なることで、金融計算や科学技術計算で予期しない結果になることがあるでしょう。
精度が重要な計算では、10進数の精度を保証するDecimal型や任意精度演算ライブラリを使用することが推奨されます。
16進数浮動小数点リテラル(C言語・C++)
C言語のC99規格以降では、浮動小数点数を16進数で直接表記する「16進数浮動小数点リテラル」がサポートされています。
C言語での16進数浮動小数点リテラル
0x1.8p0 → 1.5(1+0.5、p0は2^0を意味する指数部)
0x1.0p4 → 16.0(1×2^4)
0x1.8p1 → 3.0(1.5×2^1)
この表記法を使うと浮動小数点値を正確に指定できるため、移植性の高いコードを書く際に役立つ。
この表記法は一般的なアプリケーション開発ではあまり使われませんが、数値計算ライブラリや組み込みシステムでは重要な知識となるでしょう。
まとめ
本記事では、16進数の小数点表記の仕組み・変換手順・固定小数点・浮動小数点・精度と丸め誤差の問題まで詳しく解説してきました。
16進数の小数部分は16の負のべき乗を重みとして計算する仕組みであり、整数部分と同じ原理で変換できます。
固定小数点表現と浮動小数点表現(IEEE 754)の違いを理解することで、プログラミングにおける数値の精度問題への理解が深まるでしょう。
10進数では正確に表現できる小数が2進数・16進数では近似値になる場合があることを意識して、精度が求められる計算ではDecimal型などを活用してください。