コンピュータ演算パッケージ
Wolfram言語で使われる演算は,可変精度のソフトウェア演算と浮動小数点ハードウェアの製造元が提供したもの(浮動小数点ハードウェアがない場合はコンパイラの設計者が提供したもの)とが混ざったものである.コンピュータの浮動小数点計算一般についての基本事項について知りたい場合,または使用中のマシンでの機械計算を調べたい場合は,ComputerArithmetic`を使うとよい.これを使うとさまざまな基底,精度,丸め規則の演算について調べることができる.
ComputerNumber[x] | 通常の数 x を,現在使用中の演算におけるコンピュータ数に変換する |
ComputerNumber[sign,mantissa,exp] | 符号 sign, 仮数 mantissa, 指数 exp を持つコンピュータ数を形成する |
コンピュータ数を構成する完全なデータオブジェクト | |
NaN | 現行の演算で表示不能な数 |
ComputerArithmeticにおけるコンピュータ数と非数
コンピュータ数を構成するデータオブジェクトに含まれている情報のほとんどは不要なものである.特に,最初の3つの引数は4番目の引数と全く同じ情報を有している.この冗長さは効率のためでもあり,ユーザが多くのフィールドにアクセスできるようにするためでもある.第5引数はコンピュータ数自体とは何の関係もなく,コンピュータ数に含まれるようになったすべての丸め誤差の累積的な影響を除いた場合にその数の値がどのようなものになるかということを表す. これはWolfram言語の高精度数学をもって計算されたもので,一般にその数の正確な値であると考えられる.コンピュータ数をこの数と比較するとコンピュータ数における誤差が分かる.
SetArithmetic[n] | 演算を基底10,n 桁に設定する |
SetArithmetic[n,b] | 演算を基底 b,n 桁に設定する |
Arithmetic[] | 現在有効な演算のパラメータを与える |
演算の設定にはいくつかのオプションがある.精度と基底を変更する他に,使用する丸めのタイプ,許容する数の大きさ,混合モードの演算を許容するか否か,割算を単独の丸め操作で行うか否か等が変更できる.
オプション名
|
デフォルト値
| |
RoundingRule | RoundToEven | 使用する丸めのタイプ |
ExponentRange | {-50,50} | 許容される指数の範囲 |
MixedMode | False | 混合モードの演算を許容するか否か |
IdealDivision | False | 正しく丸められた割算を使うか否か |
SetArithmeticのオプション
正確に丸められた割算は関数IdealDivideで実装されることに注目しなければならない.この関数は演算が正確な割算を自動的に使用するかどうかに関わらず使うことができる.x/y はパッケージに認識される前に x y^(-1)に変換されるので,これを使って正確な割算を得るのは難しい.パーサが x/y を x y^(-1)に変更してしまう前に,$PreReadを使って x/y を x~IdealDivide~y に変換させて,これを避ける.自分自身の理由で$PreReadを使いたい場合は,これによって自身の定義が干渉されることがある.
RoundToEven | 表すことができる最も近くの数に丸め,最近傍の数が2つある場合は偶数の仮数で表現される数に丸める |
RoundToInfinity | 表すことができる最も近くの数に丸め,最近傍の数が2つある場合は0から離れた数に丸める |
Truncation | 正の数に対してFloorが行うように,余分な桁を単純に削除する |
計算機数学には普通の数学と異なる点が多数ある.その大部分は簡単に示すことができる.
Wolfram言語はマシンが提供する機械計算と独自の任意精度の計算の両方を使う.任意精度の計算はどんな機械を使っても同じである(表示可能な最大数の違いとマシンのメモリ量によっての違いはある).このパッケージは,マシンが提供する浮動小数点演算を扱う.
コンピュータ上の数値は離散集合である.数値の間にはギャップがあり,計算をしても結果が表示できないことがしばしばある.結果が2つの表示可能な数値の間に当たる場合は,正確な結果ではなく表示可能な数値のうちの近い方を使うことが最善である.浮動小数点数の形式でコンピュータ上で表現することのできる数の集合は,一般に機械数集合と言われる.このパッケージを使うと,計算をコントロールする特定の基本的なパラメータを変えることができる.
連続する2つの機械数の差分はulp(unit in the last place,最後の桁の単位)と呼ばれる.1 ulpの大きさは機械数集合のどの部分で演算を行っているかによって異なる.1と2の間なら1 ulpは$MachineEpsilonに等しい.2と4の間なら2$MachineEpsilonに等しい.どんな関数も2分の1 ulpを超える誤差を含む結果を返さないことが望ましい.なぜなら,真の結果から最も近くの機械数までの距離は常に2分の1 ulpより小さく,最悪の場合でも2つの機械数のちょうど中心にあるからである.四則演算と平方根関数ではこの理想に到達するのは比較的簡単である.初歩的な超越関数は1つの計算で評価することができないので,すべての丸め誤差を合わせて2分の1 ulpより小さく収めなければならないことになり,この理想を達成するのは少々難しくなる.しかし,これらの関数で誤差が1 ulpより大きくならないようなアルゴリズムを設計するのは可能である.
計算機演算パッケージは,使用しているマシンでの機械浮動小数点計算を検証するのに有益な4つの関数を提供する.
Ulp[a] | a 付近でulpの大きさを与える |
MachineError[f,x->a] | 機械計算を使って,x=a での f の評価における誤差を与える |
MicroscopePlot[f,{x,a}] | 機械計算を使って,x=a 付近での f をプロットする |
MicroscopicErrorPlot[f,{x,a}] | 機械計算を使って,x=a 付近での f の評価における誤差をプロットする |
MicroscopePlotとMicroscopicErrorPlotにおける点 x=a のデフォルトの近傍は,a の左に30ulpから a の右に30ulpの間である.ここで使用されているulpは x=a で定義されたもの,すなわちUlp[a]である.2のベキ乗付近と0付近ではulpの大きさが変化するので,どうしたらよいか定かでない.2のベキ乗付近では,ulpは2つの値の小さい方になるように選ばれていて,丸めの影響によって結果の機械数が複数回含められるので,横座標にはそれ程問題はない.近傍のデフォルトサイズは近傍指定に3番目の値を含むことで変更できる.
MicroscopePlotとMicroscopicErrorPlotでは,関数の値が無限大になる付近で問題が起こる.関数は大きさの順に急速に変化しているので,知りたい情報を表示するのによいスケールを選ぶのは困難である.そのような場合は,自分の所望する点から何百ulpか離れたところで関数を検証する必要があるかもしれない.
MicroscopePlot[f,{x,a,n}] | 機械計算を使って,x=a-n Ulp[a]から x=a+n Ulp[a]まで f をプロットする |
MicroscopicErrorPlot[f,{x,a,n}] | 機械計算を使って,x=a-n Ulp[a]から x=a+n Ulp[a]まで f を評価するときの誤差をプロットする |
オプションJoinedはプロットの描画方法をコントロールする.現在検証中の関数は機械数を機械数にマップする,ということはいくら強調しても強調しすぎることはない.我々の目的のためには,間にある実数は存在しないと言ってもよい.ゆえに,MicroscopePlotとMicroscopicErrorPlotが生成するプロットはプロットされた一群の点の集合にすぎない.しかし,その点を直線で結んでみると何が起こっているかがよく分かるようになる.最後に,関数が実数から実数へのマップとして,すなわち実際の引数を最も近くの機械数に丸めてこの結果に関数を適用することで何を行うのかを知りたければ,そのようにしても構わないが,誤差が大きくなることが分かっても,それが関数の問題だと結論付けてはならない.関数は,それが引数として受け取る機械数を扱う以上のことはできないからである.
MicroscopePlotとMicroscopicErrorPlotのオプション
丸め誤差がしばしば誤解され,誤差とは何の関係もないアルゴリズムが不当に責められるということがよくあるので,1点ここではっきりさせておく必要がある.アルゴリズムは機械数の集合を機械数の集合にマップするように設計されているため,これ以外の数を考慮に入れても意味がないのである.コンピュータに関する限り,他の数というものは存在しないのである.例えばの平方根を求めたければ次のように行う.
以下では誤差が1 ulpの半分より小さくなっている.しかし,ここでの誤差には平方根関数とaという数をbという機械数に丸めたときの丸め誤差の両方が含まれている.実際のところ,平方根関数の誤差は0.1ulpより小さい.