
丸めとは、数値を近似値、より扱いやすい値に調整するプロセスであり、多くの場合、より短く、より単純な表現で表されます。例えば、$23.4476 を $23.45 に、分数312/937 を 1/3 に、式 √2 を 1.414 に置き換えることなどがこれに該当します。
丸め処理は、元の値よりも報告や伝達が容易な値を得るためによく行われます。また、計算された数値、測定値、または推定値を誤って正確に報告することを避けるためにも、丸め処理は重要です。たとえば、123456と計算された数量が数百単位の誤差範囲内でしか正確でないことがわかっている場合、通常は「約123500」と表現する方が適切です。
一方、正確な数値を丸めると、報告結果に丸め誤差が生じます。多くの計算を報告する場合、特に整数演算または固定小数点演算で2つの数値を割り算する場合、平方根、対数、正弦などの数学関数を計算する場合、または有効桁数が固定された浮動小数点表現を使用する場合、丸めはほぼ避けられません。一連の計算では、これらの丸め誤差は一般的に蓄積され、特定の悪条件の場合には、結果が意味をなさなくなる可能性があります。
超越関数の正確な丸め処理は、切り上げか切り捨てかを判断するために計算する必要のある桁数が事前にわからないため、困難です。この問題は「表作成者のジレンマ」として知られています。
丸め処理は、物理量を数値やデジタル信号で符号化する必要がある場合に発生する量子化と多くの類似点がある。
波状の等号(≈ )は、正確な数値を丸めることを示すために使われることがあります。例:9.98 ≈ 10。この記号は、1892 年にアルフレッド・ジョージ・グリーンヒルによって導入されました。[ 1 ]
丸め処理方法の理想的な特性は以下のとおりです。
一つの方法が全ての理想的な特性を満たすことは通常不可能であるため、様々な丸め方法が存在する。
一般的に、丸めは冪等です。[ 2 ]つまり、一度丸められた数値を同じ精度で再度丸めても、その値は変わりません。丸め関数は単調でもあります。つまり、2 つの数値を同じ絶対精度で丸めても、それらの順序は入れ替わりません(ただし、同じ値になる場合があります)。離散範囲の一般的な場合、それらは区分的に定数関数です。
典型的な丸め処理の問題には以下のようなものがあります。
丸め処理の最も基本的な形式は、任意の数値を整数に置き換えることです。以下の丸めモードはすべて、抽象的な単一引数の「round()」プロシージャの具体的な実装です。これらは(乱数を使用するものを除き)真の関数です。
これら4つの方法は、整数への方向付き丸めと呼ばれます。これは、元の数値xから丸められた値yへの変位がすべて同じ極限値(0、 +∞、または−∞ )に向かうか、または遠ざかる方向になっているためです。方向付き丸めは区間演算で使用され、金融計算でしばしば必要とされます。
xが正の場合、切り捨てはゼロ方向への切り捨てと同じであり、切り上げはゼロ方向への切り捨てと同じです。xが負の場合、切り捨てはゼロ方向への切り捨てと同じであり、切り上げはゼロ方向への切り捨てと同じです。いずれの場合も、xが整数であれば、yは単にxになります。
多数の計算が連続して行われる場合、丸め方法の選択は結果に非常に大きな影響を与える可能性があります。有名な例として、 1982年にバンクーバー証券取引所が設定した新しい指数があります。当初は1,000.000(小数点以下3桁の精度)に設定されていましたが、22か月後には市場が上昇しているように見えたにもかかわらず、約520まで下落しました。この問題は、指数が毎日何千回も再計算され、常に小数点以下3桁に切り捨て(切り捨て)されていたため、丸め誤差が蓄積されたことが原因でした。同じ期間の指数を切り捨てではなく、最も近い千分の一に丸めて再計算すると、指数の値は524.811から1098.892に修正されました。[ 3 ]
以下の例では、sgn( x )は元の数値xに適用される符号関数を指します。
切り捨て(または底を取る、または負の無限大に向かって切り捨てる)することもできます。yはx を超えない最大の整数です。
例えば、23.7は23に丸められ、-23.2は-24に丸められます。
また、切り上げ(または天井を取る、または正の無限大に向かって切り上げる)することもできます。yはx以上である最小の整数です。
例えば、23.2は24に丸められ、-23.7は-23に丸められます。
また、ゼロに向かって丸める(または切り捨てる、または無限大から遠ざける)こともできます。yは、0 からx までの範囲(xを含む)にあるxに最も近い整数です。つまり、 y はxの小数部分を除いた整数部分です。
例えば、23.7は23に丸められ、-23.7は-23に丸められます。
また、ゼロから離れる方向に丸める(または無限大に向かって丸める)こともできます。yは、 x が0 とyの間にある(x を含む)ような、0 に最も近い整数です(または同等に、xに最も近い整数です)。
例えば、23.2は24に丸められ、-23.2は-24に丸められます。
これら6つの方法は、最も近い整数への丸めと呼ばれます。数値xを最も近い整数に丸めるには、 xが2つの整数のちょうど中間、つまりxの小数部分がちょうど0.5である場合のタイブレークルールが必要です。
0.5の小数部分がなければ、最も近い値に丸める方法によって生じる丸め誤差は対称的になります。つまり、切り捨てられるすべての小数(例えば0.268)に対して、同じ量だけ切り上げられる補数となる小数(つまり0.732)が存在するということです。
小数部が均等に分布する多数の固定小数点数を丸める場合、小数部が0.5の値を除いたすべての値による丸め誤差は、統計的に互いに相殺されます。つまり、小数部が0.5の値を除外した場合、丸められた数値の期待値(平均値)は、元の数値の期待値と等しくなります。
実際には、浮動小数点数が一般的に使用されるが、浮動小数点数は等間隔ではないため、計算上のニュアンスがさらに複雑になる。
半分を切り上げる(または正の無限大に向かって半分を切り上げる)という、多くの分野で広く用いられている同点時の決定ルールがあります。つまり、 xの中間値は常に切り上げられます。x の小数部分がちょうど 0.5 の場合、y = x + 0.5となります。
例えば、23.5は24に丸められ、-23.5は-23に丸められます。
JavaやPythonなどのプログラミング言語では、「半分上」という言葉は、正の無限大に向かって半分を切り上げるのではなく、ゼロから半分を切り上げることを意味します。[ 4 ] [ 5 ]
この方法は、2の補数表現や類似の表現における丸め方向を判断するために、1桁の数字を確認するだけで済みます。
一般的な切り上げとは対照的に、半分を切り捨てる(または負の無限大に向かって半分を切り捨てる)こともできます。xの小数部分がちょうど 0.5 の場合、y = x − 0.5となります。
例えば、23.5は23に丸められ、-23.5は-24に丸められます。
JavaやPythonなどのプログラミング言語では、「半分をゼロに丸める」という表現を、負の無限大に丸めるという意味ではなく、ゼロに丸めるという意味で使用しています。[ 4 ] [ 5 ]
従来のようにゼロから半分を丸めるのではなく、ゼロに向かって半分を丸める(または無限大から半分を丸める)こともできます。xの小数部分がちょうど 0.5 の場合、xが正であればy = x − 0.5、xが負であればy = x + 0.5となります。
例えば、23.5は23に丸められ、-23.5は-23に丸められます。
この方法は正の値と負の値を対称的に扱うため、元の数値が正または負である確率が等しい場合、全体的な正負の偏りは生じません。ただし、ゼロへの偏りは依然として存在します。
また、0から離れた半分(または無限大に向かって半分)に切り捨てることもできます。これは、一般的に教えられ使用されているタイブレークのルールで、xの小数部分がちょうど0.5の場合、xが正の場合はy = x + 0.5、xが負の場合はy = x − 0.5となります。
例えば、23.5は24に丸められ、-23.5は-24に丸められます。
丸める値の符号と絶対値表現を使用するコンピュータでは、この方法の方が効率的です。なぜなら、切り上げか切り下げかを判断するために、省略された最初の桁だけを考慮すればよいからです。この方法は簡便であるため、有効数字への丸めを行う際によく用いられます。
この方法は、商業的な丸め処理とも呼ばれ、正の値と負の値を対称的に扱うため、元の数値が正または負になる確率が等しい場合、全体的な正負の偏りは生じません。ただし、ゼロから離れた方向に偏りが生じるという点は変わりません。
これは、通貨換算や価格の四捨五入(金額をユーロのセントなどの最小単位に最初に変換する場合)によく使用されます。なぜなら、追加の精度桁や金額の符号に関係なく、最初の小数点のみを考慮することで簡単に説明できるからです(金額の支払者と受取人の間の厳密な等価性を確保するため)。
また、半分を偶数に丸めることもできます。これは、正負の偏りやゼロへの偏りがない同点解消ルールです。この慣例では、xの小数部分が 0.5 の場合、y はxに最も近い偶数になります。したがって、たとえば 23.5 は 24 になり、24.5 も同様です。ただし、-23.5 は -24 になり、-24.5 も同様です。この関数は、入力がほとんど正またはほとんど負であっても、ほとんど偶数でもほとんど奇数でもない限り、丸められた数値を合計するときの期待誤差を最小化します。
この最も近い丸め方法の変種は、収束丸め、統計学者の丸め、オランダ式丸め、ガウス式丸め、奇偶丸め[ 6 ]、または銀行家の丸め[ 7 ]とも呼ばれます。
これは、 IEEE 754演算において、バイナリ浮動小数点形式の結果に対して使用されるデフォルトの丸めモードです。
バイアスを排除することで、一次元ランダムウォークのように独立した数値を繰り返し加算または減算すると、誤差が線形的にではなく演算回数の平方根に比例して増加する傾向のある丸められた結果が得られます。
しかし、このルールは偶数の確率を奇数の確率よりも高くすることで分布を歪めてしまう。そのため、このルールは分布よりも合計値が重要な状況でのみ適用される。
また、半分を奇数に丸めることもできます。これは、半分を偶数に丸めるのと同様のタイブレークルールです。この方法では、xの小数部分が 0.5 の場合、yはxに最も近い奇数になります。したがって、たとえば 23.5 は 23 になり、22.5 も同様です。一方、−23.5 は −23 になり、−22.5 も同様です。
この方法は、丸める数値がほとんど偶数でもほとんど奇数でもない限り、正負の偏りやゼロに向かう偏りもゼロに向かう偏りもありません。また、偶数に対する奇数の確率を高めるため、元の分布を歪めるという半分を偶数に丸める特性も共有しています。これは、英国が通貨を十進法化した際に銀行残高に使用された方法です[ 8 ]。
このバリアントは、指数範囲が限られている浮動小数点数のスケールを拡大したくない場合を除いて、計算ではほとんど使用されません。半分を偶数に丸めると、無限でない数は無限に丸められ、小さな非正規値は通常のゼロ以外の値に丸められます。実際には、このモードは同数の既存のスケールを維持することを優先し、偶数基数の数体系(2進数や10進数など)では、可能な限り範囲外の結果を避けます。
あまり知られていない方法ですが、小数点以下が 0.5 の数値を丸める際に、切り上げ方向と切り捨て方向を交互に変える方法があります。それ以外の数値はすべて最も近い整数に丸められます。小数点以下が 0.5 の場合は、切り上げと切り捨てを交互に行います。小数点以下が 0.5 の最初の出現では切り上げ、2 回目の出現では切り捨て、といった具合です。あるいは、最初の 0.5 の小数点以下の丸めは乱数シードによって決定することもできます。「切り上げ」と「切り捨て」は、互いに反対方向の任意の 2 つの丸め方法(正の無限大に向かう方向と反対方向、またはゼロに向かう方向と反対方向)です。
0.5の小数部分の出現頻度が、出現頻度の「カウント」を再開する頻度よりも有意に高い場合、実質的にバイアスがないと言えます。バイアスがゼロであることが保証されているため、数値を合計したり平均したりする場合に役立ちます。
xの小数部分が0.5の場合、x + 0.5とx − 0.5の間で、等しい確率でyをランダムに選択します。それ以外の場合は、最も近い整数に丸めます。
偶数への切り上げや奇数への切り上げと同様に、このルールは基本的に全体的な偏りがなく、偶数と奇数のy値の間でも公平です。交互のタイブレーク方式と比較した利点は、小数点以下0.5の部分の最後の丸め方向を「記憶」する必要がないことです。
負の無限大に最も近い整数と正の無限大に最も近い整数のいずれかに、近接度に応じて確率で丸める方法は、確率的丸めと呼ばれ、平均的には偏りのない結果が得られます。[ 9 ]
例えば、1.6は0.4の確率で1に丸められ、0.6の確率で2に丸められます。
確率的丸めは、丸め関数では決して実現できない精度を実現できます。たとえば、0 から始めて 0.3 を 100 回加算し、加算のたびに合計を丸めるとします。通常の丸めでは結果は 0 になりますが、確率的丸めでは、期待される結果は 30 となり、これは丸めない場合と同じ値になります。これは、トレーニングで低精度の算術演算を反復的に使用する機械学習で役立ちます。 [ 9 ]確率的丸めは、1 次元ディザリングを実現する方法でもあります。
最も一般的な丸め処理は、整数に丸めることです。より一般的には、何らかの増分値の整数倍に丸めることです。例えば、秒の10分の1、ドルの100分の1、1/2インチや1/8インチの整数倍、12個や1000個の整数倍などに丸めます。
一般的に、数値x を特定の正の値mの倍数に丸めるには、以下の手順が必要です。
例えば、x = 2.1784ドルを整数セント (つまり 0.01 の倍数) に丸めるには、 2.1784 / 0.01 = 217.84を計算し、次にそれを 218 に丸め、最後に218 × 0.01 = 2.18 を計算します。
あらかじめ決められた有効桁数に丸める場合、増分mは丸める数値(または丸めた結果)の大きさに依存します。
増分mは通常、数値を表すために使用される記数法において有限の分数です。人間が見る場合、通常は10進数表記(つまり、mは整数に10のべき乗を掛けた値、例えば1/1000や25/100など)を用います。デジタルコンピュータに格納される中間値の場合、多くの場合、 2進数表記(mは整数に2のべき乗を掛けた値)を用います。
任意の実数値から整数を返す抽象的な単一引数関数「round()」には、整数への丸めのセクションで示されているように、少なくとも12種類の具体的な定義があります。抽象的な2引数関数「roundToMultiple()」はここで正式に定義されていますが、多くの場合、増分値m =1が暗黙的に使用され、その後、同じ12種類の具体的な定義を持つ同等の抽象的な単一引数関数に簡略化されます。
指定されたべき乗への丸めは、指定された倍数への丸めとは大きく異なります。例えば、コンピュータでは、数値を2のべき乗に丸める必要があることがよくあります。一般的に、正の数xを1以外の正の数bのべき乗に丸める手順は次のとおりです。
倍数への丸めに適用される注意点の多くは、べき乗への丸めにも適用される。
音楽の半音階「12音」では、 3 / 2は2 7/12 ( 5 度)に丸められ、 4 / 3は2 5/12 ( 4 度)に丸められ、5 / 4は2 4/12 (長 3 度)に丸められ、6 / 5は2 3/12 (短 3 度)に丸められ、9 / 8は2 2/12 (減 3 度)に丸められます。
このタイプの丸め処理は、対数スケールへの丸め処理とも呼ばれ、指定されたべき乗への丸め処理の一種です。対数スケールでの丸め処理は、値の対数を取り、対数スケール上の最も近い値に通常の丸め処理を行うことで実現されます。
例えば、抵抗器は対数スケールで推奨値で供給されます。特に、精度が10%の抵抗器の場合、100、120、150、180、220などの公称値が10の倍数に丸められて供給されます(E12シリーズ)。計算で165オームの抵抗器が必要であることが示された場合、log(150) = 2.176、log(165) = 2.217、log(180) = 2.255となります。165の対数は180の対数に最も近いため、他に考慮事項がない場合は180オームの抵抗器が第一の選択肢となります。
値x ∈ ( a , b )がaまたはbに丸められるかどうかは、二乗値x 2が積abより大きいか小さいかによって決まります。抵抗器の例では、値 165 は 180 に丸められます。これは、165 2 = 27225が150 × 180 = 27000より大きいためです。
浮動小数点演算において、丸め処理とは、与えられた値x を、指定された桁数の有効数字を持つ値yに変換することです。言い換えれば、y はxの大きさに応じて決まる数mの倍数である必要があります。数mは、浮動小数点表現の基数(通常は 2 または 10)のべき乗です。
この詳細を除けば、上記で説明した丸めのすべてのバリエーションは、浮動小数点数の丸めにも適用されます。このような丸めのアルゴリズムは、上記の「スケーリングされた丸め」のセクションで説明されていますが、定数スケーリング係数s = 1、整数基数b > 1を使用しています。
丸め結果がオーバーフローする場合、方向付き丸めの結果は、「ゼロから離れる方向に丸める」場合は適切な符号付き無限大になり、「ゼロに向かう方向に丸める」場合は表現可能な最大の正の有限数(xが負の場合は表現可能な最小の負の有限数)になります。通常の最も近い丸めの場合のオーバーフローの結果は、常に適切な無限大になります。
場合によっては、与えられた数x を「きれいな」分数、つまり分子mと分母nが指定された最大値を超えない最も近い分数y = m / nに丸めることが望ましい。この問題は、値を固定桁の十進数または二進数に丸める問題、あるいは指定された単位mの倍数に丸める問題とはかなり異なる。この問題は、ファレイ数列、スターン・ブロコット木、および連分数に関連している。
加工済みの木材、筆記用紙、電子部品、その他多くの製品は、通常、ごく少数の標準価格でのみ販売されている。
多くの設計手順では、概算値を計算し、その後「最も近い標準値に切り捨てる」、「最も近い標準値に切り上げる」、「最も近い標準値に丸める」などのフレーズを使用して、何らかの標準サイズに「丸める」方法を説明しています。[ 10 ] [ 11 ]
一連の好ましい値が対数スケール上で等間隔に配置されている場合、任意の値に最も近い好ましい値を選択することは、スケーリングされた丸めの一種と見なすことができます。このような丸められた値は直接計算できます。[ 12 ]
より一般的な丸めルールでは、任意の区切り点で値を分割することができ、例えばデータビニングなどで使用されます。関連する数学的に定式化されたツールとして、単純な差以外の距離の概念を用いるサインポストシーケンスがあります。例えば、シーケンスを最小の相対誤差(パーセント誤差)を持つ整数に丸める場合があります。
音波などの連続信号をデジタル化する場合、個々の測定値の精度よりも、多数の測定値の全体的な効果の方が重要になります。このような状況では、通常、ディザリングと、それに関連する技術である誤差拡散が使用されます。パルス幅変調と呼ばれる関連技術は、可変デューティサイクルで電力を高速にパルス化することにより、慣性デバイスからアナログタイプの出力を得るために使用されます。デルタシグマ変調は、実世界の信号とデジタル信号間の変換によく使用され、量子化の周波数統計を制御できます。
誤差拡散は、平均的に誤差が最小になるようにする手法です。1から0への緩やかな傾斜を扱う場合、誤差と現在の値の合計が0.5を超えるまでは、最初の数項は出力が0になります。0.5を超えると1が出力され、その差がこれまでの誤差から差し引かれます。フロイド・スタインバーグ・ディザリングは、画像をデジタル化する際によく用いられる誤差拡散手法です。
一次元の例として、0.9677、0.9204、0.7451、0.3091という数値が順番に現れ、それぞれを0.01の倍数に丸めるとします。この場合、累積和0.9677、1.8881 = 0.9677 + 0.9204、2.6332 = 0.9677 + 0.9204 + 0.7451、2.9423 = 0.9677 + 0.9204 + 0.7451 + 0.3091はそれぞれ0.01の倍数に丸められ、0.97、1.89、2.63、2.94となります。これらのうち最初の値と隣接する値の差から、目的の丸められた値が得られます。0.97、0.92 = 1.89 − 0.97、0.74 = 2.63 − 1.89、0.31 = 2.94 − 2.63。
モンテカルロ演算は、モンテカルロ法における手法の一つで、丸め処理をランダムに切り上げたり切り下げたりするものです。モンテカルロ演算には確率的丸め処理を用いることもできますが、一般的には、等しい確率で切り上げや切り下げを行う方法の方がよく用いられます。繰り返し実行することで、計算の安定性を示すランダムな結果分布が得られます。[ 13 ]
整数の定義域と値域を持つ関数の正確な値を求めるには、丸め演算を用いることが可能です。例えば、整数n が平方数であることが分かっている場合、nを浮動小数点数zに変換し、浮動小数点数を用いてzの近似平方根xを計算し、x を最も近い整数yに丸めることで、平方根を求めることができます。nが大きすぎなければ、 xの浮動小数点丸め誤差は0.5 未満となるため、丸められた値y はnの正確な平方根となります。これが、計算尺が正確な演算に用いられる理由の本質です。
異なる精度レベルで数値を 2 回連続して丸めると、後者の精度が粗くなるため、直接丸めの場合を除き、最終精度に 1 回丸めた場合と同じ結果が得られるとは限りません。[注 2 ]例えば、9.46 を最も近い小数点以下第 10 位に丸めると 9.5 になり、次に偶数に丸める方法で最も近い整数に丸めると 10 になりますが、同じ方法で直接丸めると 9 になります。Borman と Chatfield [ 14 ]は、1 つの小数点以下に丸めたデータを整数で表した仕様限界と比較する場合の、二重丸めの影響について議論しています。
1995年から1997年にかけて争われたマルティネス対オールステート事件とセンデホ対ファーマーズ事件では、保険会社は保険料の二重丸めは許容され、実際には義務付けられていると主張した。米国の裁判所は保険会社に不利な判決を下し、単一丸めを確実にするための規則を採用するよう命じた。[ 15 ]
一部のコンピュータ言語とIEEE 754-2008規格では、単純な計算では結果を2回丸めてはならないと規定されています。これはJavaでは特に問題となっており、Javaは異なるマシンで同じように実行されるように設計されているため、x87浮動小数点ではこれを実現するために特別なプログラミングトリックを使用する必要がありました。[ 16 ] [ 17 ] Java言語は、差が問題にならない場合は異なる結果を許容し、結果が正確に準拠する必要がある場合はstrictfp修飾子を使用する必要があるように変更されました。厳密浮動小数点がJava 17で復活しました。 [ 18 ]
一部のアルゴリズムでは、中間結果がより高い精度で計算され、その後最終精度に丸められる必要があります。中間計算に適切な丸めを選択することで、二重丸めを回避できます。これは、最終的な丸めで中間点に丸めないようにすること(中間点が正確な場合を除く)です。バイナリ演算では、結果をゼロに向かって丸め、丸められた結果が不正確な場合は最下位ビットを 1 に設定するという考え方です。この丸めはスティッキー丸めと呼ばれます。[ 19 ]同様に、中間結果が正確に表現できる場合はそれを返し、そうでない場合は奇数の仮数を持つ最も近い浮動小数点数を返します。これが、奇数への丸めとも呼ばれる理由です。[ 20 ] [ 21 ]バイナリおよび十進演算に対するこのアプローチの具体的な実装は、より低い精度に備えるための丸めとして実装されています。
この丸めモードは、複数回の丸め処理後に誤った結果が生じる可能性を回避するために使用されます。これは、最終丸めを除くすべての丸め処理を「より短い精度に備えるための丸め処理」(「RPSP」)で行い、最終丸め処理のみを外部要求モードで使用することで実現できます。
10進数演算では、入力が正確に表現できない場合、末尾の桁が0と5になることは避けられます。最下位桁が0または1、4または5、5または6、9または0のいずれかである数値を選択できる場合は、0または5以外の桁が選択されます。それ以外の場合は、選択は任意です。IBMは、後者の場合、絶対値が小さい桁が選択されると定義しています。[ 22 ] [ 23 ] RPSPは、連続する2つの丸めの間隔を1桁程度に小さくして適用できます(たとえば、1/100への丸めの後に1/10への丸めを適用できます)。たとえば、整数に丸める場合、
「二重丸め」のセクションでの例では、9.46 を小数点以下 1 位に丸めると 9.4 になり、これを整数に丸めると 9 になります。
2進数演算では、この丸めは「奇数に丸める」(「半分を奇数に丸める」と混同しないように)とも呼ばれます。たとえば、1/4(2進数では0.01)に丸める場合、
バイナリ演算で正しい結果を得るには、各丸めステップで少なくとも2つのバイナリ桁を削除する必要があります。そうしないと、誤った結果が表示される可能性があります。たとえば、
誤った中間ステップを削除すると、最終的な整数への丸め処理で 3.25 は正しい値である 3 に丸められます。
RPSPは、IBM zSeriesおよびpSeriesのハードウェアで実装されています。Pythonモジュール「Decimal」、Tclモジュール「math」、Haskellパッケージ「decimal-arithmetic」、その他おそらく他のモジュールでは、このモードはROUND_05UPまたはround05upと呼ばれています。
ウィリアム・M・カーンは、超越関数の丸め処理にかかる未知のコストを指して「テーブルメーカーのジレンマ」という用語を作り出した。
浮動小数点引数が 2 つある場合、オーバーフローやアンダーフローが発生しないため、 y w を正しく丸めるのにどれだけのコストがかかるかは誰にもわかりません。代わりに、信頼できる数学ライブラリは、基本的な超越関数をほとんどの場合ulp の半分よりわずかに大きい範囲内で、ほぼ常に ulp の範囲内で計算します。なぜy w をSQRT のように ulp の半分の範囲内で丸めることができないのでしょうか? 計算コストがどれくらいかかるか誰もわからないからです... 超越式を計算して、あらかじめ割り当てられた桁数に正しく丸めるために、どれだけの桁数を追加する必要があるかを予測する一般的な方法は存在しません。有限個の追加桁で最終的に十分であるという事実 (もし真実であれば) でさえ、深い定理かもしれません。[ 24 ]
IEEE 754浮動小数点規格では、加算、減算、乗算、除算、積和演算、平方根、および浮動小数点剰余演算において、無限精度演算の丸め結果が正しく得られることが保証されています。1985年の規格では、より複雑な関数についてはこのような保証はなく、通常は最下位ビットの精度しか得られません。しかし、2008年の規格では、準拠する実装はアクティブな丸めモードを尊重した丸め結果を正しく得られることが保証されています。ただし、これらの関数の実装は任意です。
ゲルフォンド・シュナイダーの定理とリンデマン・ワイエルシュトラスの定理を用いると、いくつかのよく知られた引数を除いて、多くの標準的な初等関数が超越的な結果を返すことが証明できます。したがって、理論的には、そのような関数を正しく丸めることは常に可能です。しかし、そのような関数を実装する場合、正しく丸められた結果が保証される前に、与えられた精度に対してどの程度正確な結果を計算する必要があるかの限界を決定するには、多くの計算時間が必要になるか、または不可能な場合があります。[ 25 ]実際には、この限界が不明な場合(または非常に大きな上限のみがわかっている場合)、実装で何らかの決定を下す必要があります(下記参照)。しかし、確率モデルによれば、特殊なケースを考慮した後、ターゲット形式の桁数の2倍に小さな定数を加えた中間精度を使用すると、非常に高い確率で正しい丸めが満たされます。
一部のプログラミングパッケージは、正しい丸め処理を提供します。GNU MPFRパッケージは、正しく丸められた任意精度の結果を返します。その他のライブラリの中には、IEEE 754倍精度(binary64)で正しい丸め処理を備えた基本関数を実装しているものもあります。
計算可能な数値の中には、桁数をどれだけ増やしても丸めた値が決定できないものがある。具体的な例は挙げられないが、これは停止問題の不確定性から導かれる。例えば、ゴールドバッハ予想が真であるが証明できない場合、次の値nを次の整数に丸めた結果は決定できない。n = 1 + 10 − k となる。ここでkは4より大きい最初の偶数で、2 つの素数の和ではない。そのような数がない場合はn = 1 となる。丸めた結果は、そのような数kが存在する場合は 2、存在しない場合は 1 となる。ただし、丸める前の値は、予想が証明できない場合でも、任意の精度で近似することができる。
丸め処理は、数値の文字列検索に悪影響を与える可能性があります。たとえば、πを4桁に丸めると「3.1416」となりますが、この文字列を単純に検索しても、「3.14159」や4桁を超えるπの値は見つかりません。一方、切り捨てはこの問題の影響を受けません。たとえば、πを4桁に切り捨てた「3.1415」を単純に文字列検索すると、 4桁を超えるπの値が見つかります。
丸めの概念は非常に古く、おそらく除算の概念そのものよりも古い。メソポタミアで発見された古代の粘土板には、60 を基数とする逆数と平方根の丸められた値を含む表が含まれている。[ 41 ] π 、1 年の長さ、月の長さ の丸められた近似値も古くからある。60を基数とする例を参照。
1940 年以来、小数点以下を半分に丸める方法は、米国規格Z25.1 およびASTM規格 E-29として使用されています。 [ 42 ]不偏丸めと統計学者丸めという用語の起源は、かなり自明です。1906 年の『確率と誤差理論』第 4 版で、ロバート シンプソン ウッドワードはこれを「コンピュータのルール」と呼び、[ 43 ]当時、数学表を計算する人間のコンピュータによって一般的に使用されていたことを示しています。たとえば、サイモン ニューカムの 1882 年頃の著書『対数表とその他の数学表』で推奨されています。[ 44 ]ルシウス タトルの 1916 年の『測定理論』では、物理的測定値を記録するための「普遍的に採用されたルール」と呼ばれています。[ 45 ]チャーチル アイゼンハートは、1940 年代までにデータ分析でこの慣行がすでに「十分に確立されていた」と述べています。[ 46 ]
銀行の丸めという用語の起源は、依然として不明瞭である。この丸め方法が銀行業務において標準であったとしても、その証拠を見つけるのは非常に困難であることが判明している。それどころか、欧州委員会の報告書「ユーロの導入と通貨金額の丸め」[ 47 ]の第2節では、銀行業務において丸めに関する標準的なアプローチはこれまで存在しなかったと示唆しており、「中間値」は切り上げるべきであると規定している。
1980年代まで、浮動小数点演算で使用される丸め方法は、通常ハードウェアによって固定されており、ドキュメントが不十分で、一貫性がなく、コンピュータのブランドやモデルごとに異なっていました。この状況は、IEEE 754浮動小数点規格がほとんどのコンピュータメーカーに採用された後に変化しました。この規格では、ユーザーが複数の丸めモードから選択でき、それぞれの場合において結果をどのように丸めるかが正確に指定されています。これらの機能により、数値計算はより予測可能でマシンに依存しないものとなり、区間演算の効率的かつ一貫した実装が可能になりました。
現在、多くの研究では5または2の倍数に丸める傾向があります。たとえば、ヨルグ・バテンは多くの研究で年齢の積み重ねを使用して、古代の人々の計算能力レベルを評価しました。彼はABCC指数を考案し、人口の識字率が測定された歴史的資料がなくても、地域間の計算能力を比較できるようにしました。[ 48 ]
ほとんどのプログラミング言語は、小数値をさまざまな方法で丸めるための関数や特別な構文を提供しています。FortranやCなどの初期の数値計算言語では、通常は切り捨て(ゼロ方向への切り捨て)という1つの方法しか提供されていませんでした。このデフォルトの方法は、小数値を整数変数に代入する場合や、配列のインデックスとして小数値を使用する場合など、特定の状況で暗黙的に適用されることがありました。その他の種類の丸めは明示的にプログラムする必要がありました。たとえば、正の数を最も近い整数に丸めるには、0.5を加えて切り捨てることで実現できました。
しかし、ここ数十年の間に、ほとんどの言語の構文と標準ライブラリには、少なくとも 4 つの基本的な丸め関数 (切り上げ、切り下げ、最も近い値への丸め、ゼロ方向への丸め) が一般的に提供されるようになりました。タイブレーク方法は、言語とバージョンによって異なる場合があり、プログラマが選択できる場合もあります。いくつかの言語は IEEE 754 浮動小数点標準に従い、これらの関数を倍精度浮動小数点引数を受け取り、同じ型の結果を返すように定義しており、必要に応じて整数に変換できます。浮動小数点型は整数型よりも範囲が広いため、このアプローチは不要なオーバーフローを回避できます。PHP などの一部の言語では、値を指定された桁数の小数 (たとえば、4321.5678 から 4321.57 または 4300) に丸める関数を提供しています。さらに、多くの言語では、printfまたは同様の文字列フォーマット関数が提供されており、小数値をユーザーが指定した桁数 (精度)に丸めた文字列に変換できます。一方、切り捨て(ゼロへの丸め)は、特に2つの整数値の除算において、多くのプログラミング言語で依然としてデフォルトの丸め方法として用いられています。
対照的に、CSSとSVGは数値と測定値に対して特定の最大精度を定義しておらず、DOMとIDLインターフェースで無限精度であるかのように文字列として扱い、公開し、整数と浮動小数点値を区別しません。ただし、これらの言語の実装では、計算された桁を限定された精度で公開する前に、これらの数値をIEEE 754倍精度浮動小数点値に変換するのが一般的です(特に標準JavaScriptまたはECMAScript [ 49 ]インターフェースバインディング内)。
一部の分野や機関では、ラウンドに関する基準や指示を定めている。
1966 年半ばに発行されたガイドライン[ 50 ]では、米国連邦気象調整官事務所が、気象データは最も近い整数に丸めるべきであり、同点の場合は「切り上げ」ルールを採用すべきであると決定した。たとえば、1.5 を整数に丸めると 2 になり、-1.5 は -1 になる。それ以前は、同点の場合は「0 から切り捨てる」ルールが採用されていた。
気象学者の中には、0.0度から-0.5度(0度と-0.5度は含まない)の間の温度を整数に丸めたことを示すために「-0」と表記する人もいます。この表記は、負の符号が重要視される場合に使用されます。負の符号の大きさは小さいですが、例えば摂氏温度を丸める場合などです。摂氏温度では、0度未満は氷点下を表します。
浮動小数点表現など、コンピュータにおける数値表現の中には、 0(別名+0)と-0を区別するものがあります。これらの場合、負の数から0に丸められるはずだった値を、 +0ではなく-0に丸めることができます。
最も近い偶数に丸めることは、銀行もこの手法を用いるため、「銀行丸め」とも呼ばれます。Microsoft Pascal Compiler for the MS-DOS Operating System User's Guide . Microsoft Corporation. 1985. p. 165. Bankers' rounding は、末尾が .5 の実数を切り捨てる際に使用されます。
つまり、奇数は偶数に切り上げられ、偶数は偶数に切り捨てられます。
n
が偶数の場合の誤差 1/2 に関して重要な事実は
、その符号が任意である、つまり他のすべての誤差の場合のように計算によって固定されていないということです。しかし、補間値の最後の丸められた数値を、半分の単位を処分する場合に偶数にするコンピュータのルールは、長期的にはこの誤差をプラスとマイナスで同じ頻度で発生させます。
ここでは、奇数の半分が必要な場合があります。[...] このような場合に採用する良いルールは、
最も近い偶数を書く
こと
です
。
分の1より明らかに小さい分数は捨てるべきであり、2分の1より大きい分数は常に1単位とみなすべきであるが、どちらの数値が近いか不明な場合は、同じくらい
近い奇数ではなく、最も近い偶数を記録
するという普遍的に採用されている規則がある。この手順の理由は、同じ量の一連の複数の測定では、記録が大きすぎる場合も小さすぎる場合も同様にあり、したがって、そのような複数の値の平均では、誤差が生じるとしても、わずかな誤差しか生じないからである。