1

三角関数の使用を必要とするいくつかのプログラミングの問題に取り組んでいます。残念ながら、math.hライブラリ内の関数は不正確なようです。次に例を示します。

#include <stdio.h>
#include <math.h>    
int main() {
  double a, b, c, d;
  a = sin(0.0);
  b = sin(90.0);
  c = cos(0.0);
  d = cos(90.0);
  printf("A = %lf\nB = %lf\nC = %lf\nD = %lf\n", a, b, c, d);
  return (0);
}

出力:

A = 0.000000
B = 0.893997
C = 1.000000
D = -0.448074

これらの関数を正確にする方法はありますか? または、シリーズを使用して独自の関数を作成する必要がありますか?

私はグーグルで検索しましたが、これまでのところ、関数を正確にする方法を見つけることができませんでしたが、シリーズを使用していました。

4

2 に答える 2

12

機能し、ラジアンsin()を期待します。cos()それらは通常「忠実」です。つまり、少なくとも数千までの引数について、数学的な結果の1 ULP以内の結果を生成します。

#include <stdio.h>
#include <math.h>    
int main() {
  double a, b, c, d;
  a = sin(0.0);
  b = sin(0.5 * 3.1415926535897932);
  c = cos(0.0);
  d = cos(0.5 * 3.1415926535897932);
  printf("A = %lf\nB = %lf\nC = %lf\nD = %lf\n", a, b, c, d);
  return (0);
}

A = 0.000000
B = 1.000000
C = 1.000000
D = 0.000000

追加するために編集:

Camilo Martinez は、「Unit in the Last Place」は少し特殊な概念だと指摘しています。簡単に言うと、有限個のdouble値があり、0 付近で密度が高くなります。

++-+-+-+---+---+-------+---------------+-------------------------------+--

計算している正確な三角関数の値は、ほとんどの場合、次の 2 つの間に収まりますdouble(唯一の例外はsin(0.0) = 0.0cos(0.0) = 1.0です)。

++-+-+-+---+---+-------+---------------+-------------------------------+--
                       |    ^          |
                     lower  |       upper
                     double |       double
                            |
                   exact (mathematical) result

doubleほとんどのライブラリは、通常の状況では、正確な結果のすぐ上または数学的な結果のすぐ下にある関数を提供します。問題の難しさを考えると、これはかなり良いです。

一部のライブラリは、すべての入力 ( も含む) に対して、正確な結果に最も近いdouble を提供する関数を提供します1E21。これは驚くべき結果です。比較的最近まで、これは高価な計算を犠牲にしてしか得られませんでしたが、今日では、この種の結果を過去の精度の低い関数とほぼ同じ速度で得ることさえできます.

最後に、適用したい数に適用することさえせず、最も近い近似値にのみsin()適用する場合があります。これは、一度修正された例の場合です。とを π/2 に適用したいのですが、π/2 は として表現できないため、適用できません。代わりに、最も近い利用可能なものにそれらを適用する必要があります(これは固定プログラムが行うことです)。cos()doublesin()cos()doubledouble

このような不正確さが悪化する可能があります。彼らが浮動小数点計算に悪評を与えたプロセスですが、実際には、浮動小数点の不正確さが複合する方法は非常に予測可能であり、浮動小数点を使用するプログラムを作成するときに考慮することができます。

于 2013-04-24T13:55:13.083 に答える