7

通常のラジアンではなく度数で引数を取る三角関数を定義し、これらの引数に対して正しく丸められた結果を計算するにはどうすればよいでしょうか?

引数をM_PI/180.0対応する関数にラジアンで渡す前に を掛けても、M_PI/180.0は π/180 ではないため、機能しません。Handbook of Floating-Point Arithmetic のセクション 5.5 では、引数の正しく丸められた積を π/180 で計算する方法が提供されていますが、一部の引数では、この積が 2 つの連続する表現可能な浮動小数点数の中間点に近くなります。ラジアンで正しく丸められた関数でさえ、間違った最終結果を生成する可能性があります。

単独または組み合わせて機能する可能性のある 2 つの戦略は、より高い精度を使用することsinpiと、CRlibmcospitanpi三角関数を使用して、それぞれとを計算することです。sin(πx)cos(πx)tan(πx)

後者の戦略では、180 で割るという問題が残りますが、これは多くの議論にとって正確ではありません。

高精度の戦略 (引数に π/180 の拡張精度表現を掛けてから、拡張精度関数をラジアンで適用する) に関しては、「正確な」ケースで問題が残る可能性があります。との唯一の有理結果はsinで得られるという定理は、ラジアン バージョンにのみ適用されます。これは明らかに次数バージョンには適用されません。浮動小数点入力 x について、sindeg(x) が 2 つの連続する表現可能な浮動小数点数の正確な中間点である場合、最終的な結果を保証するのに十分な中間精度はありません。結果は正しく丸められます。costan0

4

4 に答える 4

3

q有理数である唯一の有理数cosdeg(360q)は、分母として 1、2、3、4、または 6 を持ちます。 Joerg Jahnel によるこの論文には、セクション 6 で場の理論を使用した簡潔で美しい証明が含まれています (実際、著者はオイラーの全関数を使用して代数的数の次数を特徴付けています) cosdeg(360q)。浮動小数点数。qcosdeg(360q)

sinしたがって、@ gnasher729は、度数の引数の削減がはるかに優れているという優れた点を示していますが、答えは「実装方法とラジアンの友達とほぼ同じ」だと思います。

于 2014-08-03T15:30:35.430 に答える
2

それは難しい。良い面としては、引数を正確に +/- 45 度に減らすことができます。そのため、+/- 45 度の間で正しく丸められた結果が必要です。非常に小さな x の場合、sin (x) は約 x * (pi / 180) になり、正確に丸めるのは困難です。

たとえば、正弦関数のほぼ正確に丸められた結果を得るには、-45 <= x <= 45 を使用します。x を xhi = round (512 x) / 512 と xlo = x - xhi に分割します。sin (x 度) ≈ ax - bx^3 とします。s (x) a*xhi - b * (xhi^3) が正確に計算されるように、a と b を丸めます。剰余 sin (x 度) - s (x) を慎重に計算します。結果が小さいため、丸め誤差は非常に小さいはずです。s (x) に加算すると、ほとんどの場合、正しく丸められた結果が得られます。

于 2014-08-03T15:06:17.423 に答える
1

うーん、これは難しい質問です。いくつかの点を明確にしましょう:

  • 出力にはどの程度の精度が必要ですか? IEEE 754 単精度または倍精度ですか、それとも非標準ですか? さらに、入力、つまり度で表されるものは、通常のラジアン入力の場合と同様に、出力と同じ精度で表される必要があると思います。
  • パフォーマンス指標は何ですか? CRlibm は、正しく丸められた倍精度の結果を生成するように最適化されています。一方、MPFR は任意精度に使用されますが、倍精度出力のみが必要な場合は CRlibm よりもはるかに遅くなります。
  • あなたの作業範囲は?つまり、[最小引数、最大引数]? これは、倍精度範囲で機能するため、CRlibm にとって重要です。ただし、MPFR では問題になりません。

入力を度単位でのみ使用する義務がある場合は、基本的に MPFR を使用することをお勧めします。度数の引数に (Pi/180) を掛けると、超越数が生成されることを思い出してください。ただし、三角関数に渡されるのは、作業精度に丸められた、できれば最も近い整数に丸められた浮動小数点表現です。

次のようにすることをお勧めします。

  1. MPFR を使用し、バインディングよりもはるかに優れたパフォーマンスを提供するため、可能な限り C ライブラリを使用します。
  2. MPFR の精度をターゲットの精度よりもはるかに高く設定します。例: (ターゲットの精度 + 300)。これにより、演算の精度 ((Argument*Pi)/180) の損失を回避できます。これは、mpfr_set_default_prec() によって MPFR C ライブラリで簡単に実行できます。
  3. X_n=(Argument*Pi)/180 という操作を実行してから、Sin(X_n) または任意の関数を実行します。MPFRには一定のPiがあり、これは作業精度内で表されます
  4. 結果を目標精度に丸めます。

Muller による「初等関数」は、作業精度がターゲット精度の 2 倍よりもわずかに大きい場合、すべてではなくほとんどの困難なケースが正しく丸められることを統計的に示しています。しかし、あなたの場合、入力は理論的に超越的であるため、安全のために、パフォーマンスを犠牲にして、作業精度をターゲットよりもはるかに高くします。実際、倍精度の最終結果が必要な場合は、ほぼ 100% のケースで 10x で十分です。

低い精度、つまり単精度以下が必要な場合は、徹底的なテストを行って、すべてのケースが正しく丸められる最低の作業精度を決定することができます。

于 2014-08-03T22:39:02.230 に答える