2011-07-31 5 views
6

PI/2を浮動小数点で正確に表すことはできないので、cos(a)は決して正確なゼロを返すことはできません。浮動小数点でcos(a)が0になることはありません

このような場合は、次の擬似コードは、ブロックに入ることはありません(それが安全に除去することができる):

... 
y = h/cos(a); 
if (!isfinite(a)) 
{ 
    // handle infinite y 
} 
+0

を時々システムがそれを強制するかもしれない

は、さらに重要なのは、それはあなたの例ではyがゼロであることcos(a)なし無限できることに注意することが重要です'a'がaproxのときはゼロです。 'pi/2'に等しい。 – ja72

答えて

4

ゼロは、正確に表現できるいくつかの値の1つです。多くのシステムではsinとcosの共通の値のルックアップテーブルがあるため、正確にゼロを返すことはできません。

しかし、あなたは、デルタを使用して安全ですが、分割を行う前に、比較する:

ゼロ以外
if (Abs(cos(a)) < 0.0000001) 
{ 

} 
+2

「複数」のうちの1つですか?私は(2^64 - 2^53)に "いくつかの"という言葉を使うとは思わない。 –

+0

1/2、1/4、1/8、..... –

+1

すべての有限浮動小数点値は浮動小数点で正確に表現できます(衝撃的です、私は知っています)。 1/2、1/4だけでなく、0.333333333333333314829616256247390992939472198486328125および3.141592653589790007373494518105871975421905517578125も同様です。 –

0

cosがで計算そのものであるので、いや、これは、保証することはできませんエラーですので、その値はかなり正確にゼロになります。

7

、π/ 2の倍数に最も接近する倍精度値は6381956970095103 * 2^797であります、に等しい。したがって、すべての倍精度値xについて、我々は結合した

(an odd integer) * π/2 + 2.983942503748063...e−19 

|cos(x)| >= cos(2.983942503748063...e−19) 

これは、ライブラリ関数cosによって返された値ではなく、数学的に正確な値の境界であることに注意してください。良質な数学ライブラリを備えたプラットフォームでは、この境界は十分に良いので、cos(x)は倍精度xでゼロではないと言うことができます。実際には、これは二重にユニークではないことが判明しました。 cosが忠実に丸められている場合、このプロパティはすべてのIEEE-754基本タイプに適用されます。

しかし、これは、三角関数の引数削減が劇的に実装されていないプラットフォームでは起こり得ないとは限りません。

#include <math.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) { 
    double a = 0x1.6ac5b262ca1ffp+849; 
    double h = 0x1.0p1022; 
    printf("cos(a) = %g\n", cos(a)); 
    printf("h/cos(a) = %g\n", h/cos(a)); 
    return 0; 
} 

コンパイルおよび実行します:

scanon$ clang example.c && ./a.out 
cos(a) = -4.68717e-19 
h/cos(a) = -inf 
+0

私はこれに正確に答えたいと思っていました。そして、それの横に、0.0000001のような許容値が完全に恣意的に聞こえる理由を手がかりにしています。オーバーフロー保護は、if(abs(cos(x))<1);)のようなものでなければなりません。 –