header image

枝折

固定小数点数と浮動小数点数のはなし

CS

CREATED: 2026 / 05 / 07 Thu

UPDATED: 2026 / 05 / 07 Thu

浮動小数点数とは何かを考えてみる。

小数をコンピューターで扱う

コンピューターで小数を扱う場合、それらは基本的に以下に分類されます。

  • 固定小数点数
  • 浮動小数点数

固定小数点数とは、整数部と小数部の長さが固定された数値のデータ型です。 そのため、表現力が限られ、非常に大きな数と非常に小さな数を扱うことが苦手です。

浮動小数点数では、単精度か倍精度にもよりますが、小数部をより柔軟に持つことができる数値のデータ型です。

固定小数点数について

固定小数点数は、小数点の位置があらかじめ決まった数値表現で、例えば 8 bits で整数部 4 bits、小数部 4 bits とした場合、00101011 は次のように解釈されます。

整数部: 0010 = 2
小数部: 1011 = 0.5 + 0.125 + 0.0625 = 0.6875
→ 2.6875

シンプルですが、表現力に乏しいところがあります👀

浮動小数点数について

浮動小数点数は、小数点の位置を移動して正規化することで、より大きな値と細かい値を表現できます。

現代のコンピューターでは IEEE 754 規格に基づく浮動小数点数が広く使われています。

単精度浮動小数点数と倍精度浮動小数点数

IEEE 754 では主に以下の 2 種類が定義されています。

種別ビット数符号部指数部仮数部
単精度(float)32 ビット1 ビット8 ビット23 ビット
倍精度(double)64 ビット1 ビット11 ビット52 ビット

倍精度は単精度より広い範囲と高い精度を持ちますが、メモリ使用量(ビット数)が 2 倍に増えてます。

IEEE 754 の規格では浮動小数点数を符号部、指数部、仮数部に分けて扱うのですが、これについては次の節で触れます。

IEEE 754 のフォーマット

符号部・指数部・仮数部

浮動小数点数は 3 つのフィールドで構成されます。

  • 符号部(sign bit):0 が正、1 が負を表す。
  • 指数部(exponent):2 を基数とする指数を、バイアス表現で格納する。
  • 仮数部(mantissa):数値の小数部分を格納する。

単精度(32 bits)の場合、ビット配置は次の通りです。

[符号部 1bit][指数部 8bit][仮数部 23bit]

正規化

IEEE 754 では、仮数部を正規化した形で格納します。

正規化というのは、与えられた小数の値を 1.xxxxx × 2^e の形に変換することです。

この正規化された整数部の 1 は常に固定されるため浮動小数点数に含まれず、これによって、23 bits の仮数部で実質 24 bits 分のデータを表現できます。

たとえば、10 進小数 13.625(10) を 2 進数の単精度浮動小数点数で表現します。

整数部: 13  = 1101(2)
小数部: 0.625 = 0.101(2)

13.625 = 1101.101(2)
       = 1.101101 × 2^3  ← 正規化するとこうなる

符号部: 0(正)
指数部: 3 + 127(バイアス値)= 130 = 10000010(2)
仮数部: 10110100000000000000000(101101 に 0 を補って 23 ビット)

指数部のバイアスについて

指数部のバイアスはマイナスを表現するために利用されます。

マイナスを表現するといえば、補数(2 の補数表現)についてもそうでしたが、IEEE 754 では補数を使わずにバイアスを利用してマイナスを表現するようになっています。

これにより、指数部がマイナスの値であったとしても、2 進数で表現することができます🙆‍♂️

指数部のビットの格納値は以下のように決まります👇

格納値 = 実際の指数 + バイアス値
実際の指数 = 格納値 − バイアス値

バイアス値は精度によって異なります。

精度バイアス値指数の実際の範囲
単精度127-126 〜 +127
倍精度1023-1022 〜 +1023

これらは 2^(指数部ビット数 - 1) - 1 で決まってます。 単精度では 2^(8-1) - 1 = 127、倍精度では 2^(11-1) - 1 = 1023 と言った具合です。

2 の補数表現との違い

2 の補数と比較すると、用途と仕組みが異なります。

特性2 の補数表現バイアス表現
主な用途整数の負数表現浮動小数点数の指数部
負数の表し方ビット反転 + 1格納値 − バイアス値

なぜバイアス表現が指数部に使われているかというと、その格納値をそのまま符号に関係なく扱えるため(比較できるため)です。

そうすることで、浮動小数点数同士の大小比較を、符号部・指数部・仮数部全体のビット列の比較だけで行うことができます(2 の補数表現みたいにビット反転とかは考慮せず、計算がしやすくなる)。

Decimal(10 進小数)

指数表現 e

プログラミングでは、浮動小数点数の指数表記として e(または E)が使われます。 1.5e31.5 × 10^3 = 1500 を意味します。

1.5e3   →  1500.0
3.0e-2  →  0.03
6.02e23 →  6.02 × 10^23(アボガドロ定数など)

丸め誤差について

小数に関連して、10 進小数と 2 進小数の間に生まれる誤差についても触れます。

データベースとかで 10 進小数を格納すると、内部的にはその値は 2 進数として扱われます。

でも、全ての 10 進小数が有限な 2 進小数で表現できるとは限りません。

以下のように、0.5(10)0.25(10) は 2 進小数でも有限な値になりますが、0.1(10)0.3(10) は無限循環小数になってしまいます👇

0.5(10)  = 0.1(2)                        ← 有限で表現可能
0.25(10) = 0.01(2)                       ← 有限で表現可能
0.1(10)  = 0.00011001100110011...(2)     ← 無限循環小数
0.3(10)  = 0.01001100110011001...(2)     ← 無限循環小数

でも、データベースなどのシステムには無限な値を格納することはできません。 そんなことしようものならメモリがすぐにいっぱいになって動かなくなってしまいます。

なので、桁に上限を設定します。小数部は 10 桁まで、みたいな感じで。

そうすると、無限小数は途中で切る必要があります。そして、その切った時には切り捨てや四捨五入が発生するわけです。

これにより、元々入力された 10 進小数とデータベースなどに格納された 2 進小数を再度取り出した時に復元された 10 進小数の間にずれが発生してしまいます。 これがいわゆる丸め誤差です。

イメージ、以下のようなことが起こるわけです👇

0.1 + 0.2 = 0.30000000000000004

0.10.2 は 2 進数の浮動小数点数では正確に表現できないので、これが誤差となって現れるのです。

これを回避するためには、MySQL などでは Decimal 型(10 進数の浮動小数点として扱う型)を利用するといった方法が考えられます。

まあこれは使ってるツールとかによるって感じですね👀

を仕舞い

参考資料📕