浮動小数点数
MATLAB® では、浮動小数点数が倍精度または単精度のいずれかの形式で表わされます。既定は倍精度ですが、簡単な変換関数を使用して任意の数値を単精度に変換することができます。
倍精度浮動小数点
MATLAB では、倍精度に関する IEEE® Standard 754 に従って、倍精度 (double
) データ型が作成されます。double
として保存されるすべての値には 64 ビットが必要で、以下の表の形式を使用します。
ビット | 使用方法 |
---|---|
| 符号 ( |
|
|
| 数値 |
単精度浮動小数点
MATLAB では、単精度に関する IEEE Standard 754 に従って、単精度 (single
) データ型が作成されます。single
として保存されるすべての値には 32 ビットが必要で、以下の表の形式を使用します。
ビット | 使用方法 |
---|---|
| 符号 ( |
|
|
| 数値 |
MATLAB では、32 ビットで single
型の数値が保存されるので、64 ビットを使用する double
型の数値より必要メモリが少なくなります。ただし、single
型の数値は、保存する場合の使用ビットが少ないので、double
型の数字より精度が低くなります。
浮動小数点データの作成
約 3.4 x 10 38 より大きい、あるいは約 -3.4 x 10 38 より小さい値を保存するには、倍精度を使用します。これら 2 つの範囲の間にある数に対しては、倍精度または単精度のいずれかを使用することができますが、必要なメモリは単精度の方が少なくて済みます。
倍精度データの作成
MATLAB では既定の数値型が double
であるため、簡単な代入ステートメントを使用して double
を作成できます。
x = 25.783;
関数 whos
により、MATLAB で x
に保存したばかりの double
型の値のために、1 行 1 列の配列が作成されたことが示されます。
whos x Name Size Bytes Class x 1x1 8 double
x
が浮動小数点数であることを確かめたい場合は、isfloat
を使用します。この関数は、入力が浮動小数点数の場合、logical 1 (true
) を返し、それ以外の場合、logical 0 (false
) を返します。
isfloat(x) ans = logical 1
数値データ、文字または string、logical データを、MATLAB 関数 double
で倍精度に変換できます。この例では、符号付きの整数を倍精度の浮動小数点に変換します。
y = int64(-589324077574); % Create a 64-bit integer x = double(y) % Convert to double x = -5.8932e+11
単精度データの作成
MATLAB では既定の設定により、数値データが double
として保存されるため、単精度数値を作成するには変換関数 single
を使用しなければなりません。
x = single(25.783);
関数 whos
からは、変数 x
の属性が構造体で返されます。この構造体の bytes
フィールドは、x
を double
として保存する場合には 8 バイト必要であるのに対し、single として保存する場合は、4 バイトだけで済むことを示します。
xAttrib = whos('x'); xAttrib.bytes ans = 4
数値データ、文字または string、logical データを、関数 single
で単精度に変換できます。この例では、符号付きの整数を単精度の浮動小数点に変換します。
y = int64(-589324077574); % Create a 64-bit integer x = single(y) % Convert to single x = single -5.8932e+11
浮動小数点数の算術演算
この節では、浮動小数点数の算術演算で使用できるデータ型について説明します。
倍精度の演算
基本的な算術演算は、double
型、および次のその他のデータ型に実行できます。1 つ以上のオペランドが整数 (スカラーまたは配列) の場合、double
のオペランドはスカラーでなければなりません。特に注意書きがなければ、結果は double
型になります。
single
— 結果は次の型になります。single
double
int*
またはuint*
— 結果は、整数オペラントと同じデータ型をもちます。char
logical
この例は、char
型と double
型のデータに算術演算を行います。結果は double
型になります。
c = 'uppercase' - 32; class(c) ans = double char(c) ans = UPPERCASE
単精度の演算
single
型、および次のその他のクラスに、基本的な算術演算を実行できます。結果は、常に single
型になります。
single
double
char
logical
この例では、7.5 は既定の double
型で、結果は single
型です。
x = single([1.32 3.47 5.28]) .* 7.5; class(x) ans = single
浮動小数点クラスの最大値と最小値
double
と single
クラスでは、データ型で表現可能な最大値と最小値が存在します。
倍精度値の最大と最小
MATLAB の関数 realmax
と関数 realmin
は、double
データ型で表現可能な最大値および最小値を返します。
str = 'The range for double is:\n\t%g to %g and\n\t %g to %g'; sprintf(str, -realmax, -realmin, realmin, realmax) ans = The range for double is: -1.79769e+308 to -2.22507e-308 and 2.22507e-308 to 1.79769e+308
realmax
より大きい値、または -realmax
より小さい値には、正と負の無限値がそれぞれ代入されます。
realmax + .0001e+308 ans = Inf -realmax - .0001e+308 ans = -Inf
単精度値の最大と最小
MATLAB の関数 realmax
と関数 realmin
は、引数 'single'
を使用して呼び出すと、single
データ型で表現可能な最大値および最小値を返します。
str = 'The range for single is:\n\t%g to %g and\n\t %g to %g'; sprintf(str, -realmax('single'), -realmin('single'), ... realmin('single'), realmax('single')) ans = The range for single is: -3.40282e+38 to -1.17549e-38 and 1.17549e-38 to 3.40282e+38
realmax('single')
より大きい値、または -realmax('single')
より小さい値には、正と負の無限値がそれぞれ代入されます。
realmax('single') + .0001e+038 ans = single Inf -realmax('single') - .0001e+038 ans = single -Inf
浮動小数点データの精度
浮動小数点演算の計算結果が、予想した精度でない場合、コンピューターのハードウェアの制限が原因である可能性があります。おそらく、ハードウェアに完全な精度で結果を表すために十分なビットがないために、結果の端数が切り捨てられ、結果は正確でなくなったと考えられます。
倍精度数の精度
倍精度数は有限個しかないので、倍精度ストレージですべての数を表すことはできません。すべてのコンピューターにおいて、各倍精度の数と次に大きい倍精度の数の間には小さなギャップがあります。関数 eps
を使用して、結果の精度を制限するこのギャップのサイズを決めることができます。たとえば、5
と次に大きい倍精度数の間隔を求めるには、次のように入力します。
format long eps(5) ans = 8.881784197001252e-16
これは、5 と 5 + eps(5)
の間に倍精度の数が存在しないことを示します。倍精度の計算で答えとして 5 が返された場合、この結果は eps(5)
の範囲で正確であるにすぎません。
eps(x)
の値は、x
に依存します。この例は、x
が大きくなるにつれて、eps(x)
も大きくなることを示しています。
eps(50) ans = 7.105427357601002e-15
入力引数なしで eps
を実行すると、MATLAB から eps(1)
、つまり 1
と次に大きい倍精度数値の差が返されます。
単精度数の精度
同様に、任意の 2 つの単精度数間にもギャップが存在します。x
が single
型をもつ場合、eps(x)
は、x
と次に大きい単精度数間の間隔を返します。たとえば、
x = single(5); eps(x)
では、以下が返されます。
ans = single 4.7684e-07
この結果は eps(5)
より大きいことに注意してください。単精度数は倍精度数よりも数が少ないので、単精度数間の差は、倍精度数間の差よりも大きくなります。これは、単精度演算の結果は、倍精度演算の結果よりも精度が低くなることを意味します。
double
型の数 x
に対し、eps(single(x))
によって x
を double
から single
に変換する際に丸められる量の上限が与えられます。たとえば、倍精度数 3.14
を single
に変換する場合、次のように丸められます。
double(single(3.14) - 3.14) ans = 1.0490e-07
3.14
で丸められた値は、次の数値より大きくなることはありません。
eps(single(3.14)) ans = single 2.3842e-07
浮動小数点演算によくある問題の回避
MATLAB での大部分の演算は、IEEE Standard 754 に従う倍精度演算で行われます。コンピューターは数値を有限の精度 (仮数 52 ビットに対する倍精度の呼び出し) で表すだけなので、数学的にわかりにくい計算結果が生じることがあります。これらの結果は MATLAB のバグではないことに注意してください。
以下の例を使用して、これらのケースを確認してください。
例 1 — 四捨五入、あるいは予想外の結果になる場合
10 進数 4/3
は、2 進数の分数として厳密に表現することができません。このため、次の計算はゼロにはならず、eps
量が示されます。
e = 1 - 3*(4/3 - 1) e = 2.2204e-16
同様に、0.1
は 2 進数の数として正確には表現することができません。したがって、次のような直観的でない動作を示します。
a = 0.0; for i = 1:10 a = a + 0.1; end a == 1 ans = logical 0
計算では演算の順序が重要であることに注意してください。
b = 1e-16 + 1 - 1e-16; c = 1e-16 - 1e-16 + 1; b == c ans = logical 0
浮動小数点数間にはギャップがあります。以下からわかるように、数が大きくなると、ギャップも大きくなります。
(2^53 + 1) - 2^53 ans = 0
pi
は実際には π ではないので、sin(pi)
も正確にゼロにはなりません。
sin(pi) ans = 1.224646799147353e-16
例 2 — 非常に問題のある打ち消し (Catastrophic Cancellation)
ほとんど等価なオペランドどうしの減算では、予想外の打ち消しが起こることがあります。以下はスワンピング (加算を無効にする精度の損失) による打ち消しの例です。
sqrt(1e-16 + 1) - 1 ans = 0
非常に問題のある打消しの影響を取り除くため、expm1
や log1p
などの MATLAB 関数が使用される場合があります。
例 3 — 浮動小数点数の演算と線形代数
線形代数の問題を解く場合に、丸め、打ち消しおよびその他の浮動小数点数の特性が組み合わさって、計算結果が予想外のものになることがあります。次の行列 A
は条件が悪いため、Ax = b
系が小さな摂動に敏感になるという警告が表示されます。
A = diag([2 eps]); b = [2; eps]; y = A\b; Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.110223e-16.
これらは、IEEE 浮動小数点演算が MATLAB での計算にどのように影響するかを示すいくつかの例にすぎません。IEEE 754 算術演算で行われたすべての計算が影響を受けることに注意してください。これは MATLAB だけでなく、C や FORTRAN で記述されたアプリケーションを含みます。
参照
[1] Moler, Cleve. “Floating Points.” MATLAB News and Notes. Fall, 1996.
[2] Moler, Cleve. Numerical Computing with MATLAB. Natick, MA: The MathWorks, Inc., 2004.