浮動小数点数
"浮動小数点" とは、分数や小数を含む実数をエンコードする一連のデータ型を指します。浮動小数点データ型では、小数点以下の桁数は可変です。一方、固定小数点データ型では小数点の前後に特定の桁数が予約されています。したがって、浮動小数点データ型は、固定小数点データ型よりも広範囲の数値を表すことができます。
数値の表現と保存用のメモリは限られているため、コンピューターは有限の精度をもつ浮動小数点数の有限集合を表現できます。この有限の精度では、一部の数値は正確に表現されないため、正確な値や高精度が求められる浮動小数点計算の精度が制限されることがあります。浮動小数点数は、その制限にもかかわらず、計算が速く、現実世界の問題を解くのに十分な精度と範囲を備えているため、広く使用されています。
MATLAB での浮動小数点数
MATLAB® には、IEEE® Standard 754 に準拠した倍精度 (double
) および単精度 (single
) の浮動小数点数のデータ型があります。既定では、MATLAB は倍精度で浮動小数点数を表します。倍精度では、数値をより高い精度で表現できますが、単精度よりも多くのメモリが必要になります。メモリを節約するために、関数 single
を使用して数値を単精度に変換できます。
倍精度または単精度を使用して、約 –3.4 × 1038 から 3.4 × 1038 までの数値を保存できます。この範囲外の数値がある場合は、倍精度を使用して保存します。
倍精度データの作成
MATLAB の既定の数値型は double
型であるため、単純な代入ステートメントで倍精度の浮動小数点数を作成できます。
x = 10; c = class(x)
c = 'double'
関数 double
を使用して、数値データ、文字または string、および logical データを倍精度に変換できます。たとえば、符号付き整数を倍精度の浮動小数点数に変換します。
x = int8(-113); y = double(x)
y = -113
単精度データの作成
単精度の数値を作成するには、関数 single
を使用します。
x = single(25.783);
また、関数 single
を使用して、数値データ、文字または string、および logical データを単精度に変換することもできます。たとえば、符号付き整数を単精度の浮動小数点数に変換します。
x = int8(-113); y = single(x)
y = single -113
MATLAB が浮動小数点数を保存する方法
MATLAB は、IEEE 形式に従って double
および single
の浮動小数点データ型を作成し、既定では "最も近い整数に丸め、等しい場合は偶数に丸める" という丸めモードに従います。
浮動小数点数 "x" の形式は以下のとおりです。
ここで以下のようになります。
"s" は符号を判別します。
"f" は小数部 ("仮数") であり、0 ≤ f < 1 を満たします。
"e" は指数です。
"s"、"f"、および "e" はそれぞれ、メモリの有限のビット数によって決定されます。"f" と "e" はデータ型の精度に依存しています。
次の表に示すように、double
の数値の保存には 64 ビット必要です。
ビット | 幅 | 使用方法 |
---|---|---|
63 | 1 | 符号を格納します。0 は正、1 は負です。 |
62 ~ 52 | 11 | 1023 でバイアスされた指数を格納します。 |
51 ~ 0 | 52 | 仮数を格納します。 |
次の表に示すように、single
の数値の保存には 32 ビット必要です。
ビット | 幅 | 使用方法 |
---|---|---|
31 | 1 | 符号を格納します。0 は正、1 は負です。 |
30 ~ 23 | 8 | 127 でバイアスされた指数を格納します。 |
22 ~ 0 | 23 | 仮数を格納します。 |
浮動小数点データ型の最大値と最小値
倍精度および単精度のデータ型には、表現できる最大値と最小値があります。表現可能な範囲外の数値には、正または負の無限大が代入されます。ただし、連続する浮動小数点数間のギャップが原因で、表現可能な範囲内の一部の数値は正確に格納できません。該当する数値では、丸め誤差が生じることがあります。
倍精度値の最大と最小
関数 realmax
と関数 realmin
をそれぞれ使用して、double
データ型で表現できる正の最大値と最小値を確認します。
m = realmax
m = 1.7977e+308
n = realmin
n = 2.2251e-308
realmax
および realmin
は、正規化された IEEE 値を返します。realmax
と realmin
に -1
を掛けることで、負の最大値と最小値を確認できます。realmax
より大きい値、または –realmax
より小さい値には、正または負の無限大の値がそれぞれ代入されます。
単精度値の最大と最小
引数 "single"
を指定して関数 realmax
および realmin
を呼び出すことで、single
データ型で表現できる正の最大値と最小値を確認します。
m = realmax("single")
m = single 3.4028e+38
n = realmin("single")
n = single 1.1755e-38
realmax("single")
と realmin("single")
に –1
を掛けることで、負の最大値と最小値を確認できます。realmax("single")
より大きい値、または –realmax("single")
より小さい値には、正または負の無限大の値がそれぞれ代入されます。
浮動小数点の最大連続整数
すべての整数が浮動小数点データ型を使用して表現できるわけではありません。"最大連続整数" の "x" とは、"x" 以下のすべての整数を正確に表現できるが、x + 1 を浮動小数点形式で表現できない最大の整数です。関数 flintmax
は、最大連続整数を返します。たとえば、関数 flintmax
を使用して、倍精度の浮動小数点形式の最大連続整数 (253) を確認します。
x = flintmax
x = 9.0072e+15
単精度の浮動小数点形式の最大連続整数 (224) を確認します。
y = flintmax("single")
y = single 16777216
整数データ型を浮動小数点データ型に変換すると、浮動小数点形式で正確に表現できない整数は精度が失われます。浮動小数点数である flintmax
は、同じビット数を使用して整数データ型で表現できる最大の整数よりも小さくなります。たとえば、倍精度の flintmax
は 253 ですが、int64
型の最大値は 264 – 1 です。したがって、253 より大きい整数を倍精度に変換すると、精度が失われます。
浮動小数点データの精度
浮動小数点データの精度は、次のようないくつかの要因の影響を受けることがあります。
コンピューターのハードウェアの制限 — たとえば、メモリが不十分なハードウェアでは、浮動小数点計算の結果が切り捨てられます。
各浮動小数点数と次に大きい浮動小数点数の間のギャップ — これらのギャップはどのコンピューターにも存在し、これによって精度が制限されます。
浮動小数点数間のギャップ
関数 eps
を使用して、連続する浮動小数点数間のギャップのサイズを判別できます。たとえば、5
と次に大きい倍精度数の間隔を求めます。
e = eps(5)
e = 8.8818e-16
5
から 5 + eps(5)
までの数値は倍精度形式で表すことができません。倍精度の計算で答えとして 5
が返された場合、この結果は eps(5)
の範囲内で正確です。この精度の半径は、"計算機イプシロン" とよく呼ばれます。
浮動小数点数間のギャップは均一ではありません。たとえば、1e10
と次に大きい倍精度数との間のギャップは、5
と次に大きい倍精度数との間のギャップよりも大きくなっています。
e = eps(1e10)
e = 1.9073e-06
同様に、5
と次に大きい単精度数の間の間隔を求めます。
x = single(5); e = eps(x)
e = single 4.7684e-07
単精度数の方が数が少ないため、単精度数間のギャップは倍精度数間のギャップよりも大きくなります。したがって、単精度計算の結果は、倍精度計算の結果よりも精度が低くなります。
倍精度数を単精度数に変換する際には、関数 eps
を使用して数値を丸める量の上限を決定できます。たとえば、倍精度数 3.14
を単精度に変換する際に、数値を丸める量の上限を eps(single(3.14))
に制限します。
連続する浮動小数点整数間のギャップ
関数 flintmax
は、浮動小数点形式の最大連続整数を返します。この値を超えると、連続する浮動小数点整数には 1
より大きなギャップが生じます。
eps
を使用して、flintmax
と次の浮動小数点数の間のギャップを求めます。
format long
x = flintmax
x = 9.007199254740992e+15
e = eps(x)
e = 2
eps(x)
が 2
であるため、正確に表現できる次に大きい浮動小数点数は x + 2
です。
y = x + e
y = 9.007199254740994e+15
x
に 1
を加算すると、結果は x
に丸められます。
z = x + 1
z = 9.007199254740992e+15
浮動小数点数の算術演算
浮動小数点数の算術演算ではさまざまなデータ型を使用でき、結果のデータ型は入力型によって異なります。ただし、異なるデータ型が含まれる演算を実行すると、近似や中間変換が原因で、一部の計算が正確にならないことがあります。
倍精度のオペランド
double
型、および次の任意のデータ型で基本的な算術演算を実行できます。1 つ以上のオペランドが整数のスカラーまたは配列の場合、double
のオペランドはスカラーでなければなりません。特に注意書きがなければ、結果は double
型になります。
single
— 結果はsingle
型になります。double
int8
、int16
、int32
、int64
— 結果は、整数オペラントと同じデータ型になります。uint8
、uint16
、uint32
、uint64
— 結果は、整数オペラントと同じデータ型になります。char
logical
単精度のオペランド
single
型、および次の任意のデータ型で基本的な算術演算を実行できます。結果は single
型になります。
single
double
char
logical
浮動小数点演算での予期しない結果
MATLAB での大部分の演算は、IEEE Standard 754 に準拠した倍精度演算で実行されます。コンピューターは数値を有限の精度で表現するため、一部の計算では数学的に直感的ではない結果が得られることがあります。浮動小数点数での計算時に発生することがある一般的な問題には、丸め誤差、打ち消し、スワンピング、中間変換があります。予期しない結果は MATLAB のバグではなく、浮動小数点数を使用する任意のソフトウェアで発生します。数値の正確な有理数表現を実現するには、Symbolic Math Toolbox™ の使用を検討してください。
丸め誤差
浮動小数点数の有限精度表現が原因で丸め誤差が生じることがあります。たとえば、数値 4/3
は 2 進数の分数として正確に表すことができません。そのため、次の計算では、0
ではなく、数量 eps(1)
が返されます。
e = 1 - 3*(4/3 - 1)
e = 2.2204e-16
同様に、pi
は π の正確な表現でないため、sin(pi)
は正確にはゼロになりません。
x = sin(pi)
x = 1.2246e-16
丸め誤差は、浮動小数点数に対して多くの演算が実行され、誤差が累積して大きくなった場合に最も目立ちます。ベスト プラクティスとして、可能な限り演算の数を最小化してください。
打ち消し
eps
で測定される、ほぼ同じ大きさの別の数値から数値を減算すると、打ち消しが生じることがあります。たとえば、eps(2^53)
は 2
であるため、数値 2^53 + 1
と 2^53
は同じ浮動小数点表現になります。
x = (2^53 + 1) - 2^53
x = 0
可能であれば、打ち消しを回避する等価の形式で計算を書き直すようにしてください。
スワンピング
スワンピングは、何桁も大きさが異なる浮動小数点数に対して演算を実行すると生じることがあります。たとえば、次の計算では、加算を無効にする精度の低下が示されています。
x = 1 + 1e-16
x = 1
中間変換
さまざまなデータ型が含まれた算術演算を実行すると、中間の計算と変換により、予期しない結果が生じることがあります。たとえば、x
と y
は両方とも 0.2
ですが、それらを減算すると非ゼロの結果が得られます。その理由は、まず y
を double
に変換してから減算が行われるからです。その後、この減算結果が single
の z
に変換されます。
format long
x = 0.2
x = 0.200000000000000
y = single(0.2)
y = single 0.2000000
z = x - y
z = single -2.9802323e-09
線形代数
上記のような浮動小数点演算における一般的な問題は、線形代数の問題に適用すると、複合して大きくなる可能性があります。これは、関連する計算が通常、複数のステップで構成されているからです。たとえば、線形方程式系 Ax = b
を解く場合、MATLAB は、オペランド行列 A
の条件が適切でないため、結果が不正確になる可能性があると警告します。
A = diag([2 eps]); b = [2; eps]; x = A\b;
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.110223e-16.
参照
[1] Moler, Cleve. Numerical Computing with MATLAB. Natick, MA: The MathWorks, Inc., 2004.