2011-07-12 14 views
7

私は(ほぼ)IEEE 854準拠の浮動小数点実装をTeX(これは32ビット整数のみをサポートしています)に書いています。この標準は、+-*/、比較、剰余、およびsqrtの結果を指定します。これらの操作のために、結果は、(丸めモードに従って)表現可能な数値に厳密な結果を丸めると同一であるべきです。非常に大きな正弦波の標準

IEEEは、超越関数(sinexp ...)が忠実な結果をもたらすべきであることを指定していることを思い出しているようです(デフォルトの丸めモードでは、正確な結果を表す2つの表現可能な数値)。小数の正弦を計算することは簡単です:[0,2 * pi]の範囲の数値を得るために2 * piの倍数だけシフトさせ、[0、pi/4] 、およびテイラーシリーズを使用します。

ここで、sin(1e300)を計算したいとします。そのためには、1e300 modulo 2 * piを見つける必要があります。それはpiの300(316?)小数を知ることを必要とします、なぜなら16小数しかないので、結果は何の意味も持たないからです(特に忠実ではありません)。

sin(1e300)の結果と同様の非常に大きな数値には何の基準がありますか?

他の浮動小数点実装は何をしますか?

+1

+1興味深い問題の良い説明(これまで考えていなかった) – pavium

答えて

8

超越関数の忠実な丸めを必要とする標準はありません。 IEEE-754(2008)は、を推奨していますが、これらの関数が正しく丸められる必要はありません。

ほとんどの優れた数学ライブラリは、すべての範囲(正確には、sin()の巨大な入力および同様の困難なケースであっても)に忠実に丸めた結果を提供するよう努めています。あなたが注意するように、これは、図書館がπの幾分多くの桁を知っていなければならず、表現可能な最大の数字に桁があることを必要とする。これを「無限π」引数削減と呼びます。

良い数学ライブラリは、入力が無限に正確である(すなわち、入力が常に正確に表されているかのように振舞う)という観点を採用しています。これが合理的な立場かどうか議論することはできますが、本質的にすべての良い数学図書館の実用的な前提です。

簡単な経路をとり、基本的にsin()のような機能を扱う「有限pi」リダクションを使用するライブラリがたくさんあります。これはπが表現可能な有限数であるかのようです。これは実際にのためにほとんどの問題を引き起こさないことが判明し、の使用が確実に実現しやすくなります。

+0

"無限個の引数の削減"は、大きな引数を持つときに役立ちますが、*非常に*大きな引数を持つときは役に立ちません。ライブラリは入力が正確であると仮定しても問題ありませんが、入力+イプシロン==入力してもそれ以上は重要ではありません。 – spraff

+1

@spraff:後方エラー分析*の目的で*重要ではありません。他の形式のエラー解析が使用されても問題はありません。それは最高の数学ライブラリが持つ標準です。例えば、K.C.議論のためのNgの「最後のビットへの良い」 –

+0

3番目のパラグラフでは、IEEE-754(2008)が浮動小数点数を無限に正確に考えるので、良いライブラリがこれを行うことに注意してください。簡単なルートを取る人たちと比べて「良い数学ライブラリ」の例を挙げてください。私はそれがあなたの答えに加わると思う。簡単なルートが大きな問題を引き起こさない理由の1つは、sin(2x)= 2 * sin(x)* cos(x)のような三角法のアイデンティティに違反しないということです。 –

0

あなたは、このような大量の操作をやっている場合は、もちろんあなたは精度が不足するつもりだ:

#include <iostream> 
#include <math.h> 

int main() { 
    long double i = 1; 
    std :: cout << sin (i) << "\n" << sin (i+0.1) << "\n"; 
    i = pow (10, 300); 
    std :: cout << sin (i) << "\n" << sin (i+0.1); 
} 

出力:

0.841471

0.891207

-0.817882

-0.81788

入力を正確に表現できない場合は、出力を正確に表現できません。 pi*pow(10,int(log_10(n/pi))を引いたり、「小さな」ものを悪化させるものはnだが、nが適切に大きくなると、雑音にノイズが追加されてしまい、それ以上は問題にならない。

+2

「1e300 + 2pi」=「1e300-2pi」=「1e300」なので、 '1e300'は' sin'として何らかの値を持つことができますか? –

+1

@Damien_The_Unbeliever '1e300'が最も近い表現可能な' double'値に丸められたとき、その丸めは長さ '1e284'の間隔をほぼ超えています。したがって、 '1e300'を表現可能な' double'に丸めると、非常に多くの '2pi'の長さの期間を"通過 "します。だから、「罪」を取ることは無意味です。それでも、数学的には、引数を表現可能な値に丸めた後、その正確な引数の「sin」を計算することは可能です。そうするには、2piの表現の精度が必要です。私が他の答えに対するコメントで言ったように、.NETでは、 'Sin(1e300)== 1e300'です。 –