次数引数を指定したトリガー関数が-0.0を返すのはいつですか?


10

トリグ関数を作成する際にmy_sind(d)my_cosd(d)my_tand(d)、度引数はなくラジアンいずれかを使用し、90の倍数で正確な回答を提供される、私は結果が時々あったことに気づいた-0.0のではなく0.0

my_sind( 0.0) -->  0.0
my_sind(-0.0) --> -0.0

my_sind(180.0) --> -0.0
my_sind(360.0) -->  0.0

sin()そしてtan()、典型的には、所与の記号ゼロ入力に対して同じ符号ゼロ結果を返します。これは、意味になりmy_sin()一致している必要がありsin()、それらの入力のために。

my_sind( 0.0) alike sin( 0.0) -->  0.0
my_sind(-0.0) alike sin(-0.0) --> -0.0

質問です:全体の数は、何のためにnon_zero_n/結果は、これまで返すことがなければならない-0.0ためmy_sind(180*non_zero_n)my_cosd(180*n + 180)my_tand(180*non_zero_n)

コードを書くのは簡単なので、それをf(-0.0)生成して実行するだけ-0.0です。他の(ゼロ以外の)に対して他の f(x)リターンを行う理由があるかどうか、そのサインを保証することの重要性について簡単に疑問に思います。-0.0x


注:これは、なぜ0.0vs -0.0が発生するかという問題ではありません。これが理由でcos(machine_pi/4)戻りません0.0。これは、0.0またはの生成を制御する方法の問題でもありません-0.0。私はそれをデザインの問題と考えています。

回答:


4

「最小の驚き」という設計原則は、以前に確立された機能をガイダンスとして検討することを示唆しています。この場合、最も近い確立された機能はによって提供されsinpi及びcospiIEEE規格754-2008(浮動小数点演算のためのIEEE規格)に導入機能部9これらの関数は、現在のISO CおよびISO C ++標準の一部ではなく、 CUDAなど、さまざまなプログラミングプラットフォームの数学ライブラリに組み込まれています。

これらの関数は、sin(πx)とcos(πx)を計算します。ここで、πとの乗算は関数内で暗黙的に発生します。tanpiは定義されていませんが、数学的な同等性に基づいて、に従って機能を提供すると想定できますtanpi(x) = sinpi(x) / cospi(x)

私たちは、今定義することができsind(x) = sinpi(x/180)cosd(x) = cospi(x/180)tand(x) = tanpi(x/180)直感的に。IEEE-754のセクション9.1.2では、sinpiおよびの特別な引数の処理について詳しく説明していcospiます。特に:

正の整数nの場合、sinPi(+ n)は+ 0、sinPi(−n)は−0です。これは、適切な丸めモードで、sinPi(−x)と−sinPi(x)がすべてのxで同じ数(または両方ともNaN)であることを意味します。cosPi(n +½)は、n +½が表現可能な場合、任意の整数nに対して+0です。

IEEE 754-2008標準は、引用された要件の根拠を提供していませんが、関連セクションの初期のドラフトは次のように述べています。

関数の値がゼロの場合、この0の符号は、数学関数の符号関数の連続的な拡張を考慮することによって最もよく決定されます。

754ワーキンググループのメールアーカイブを熟読すると、追加の洞察が得られる可能性があります。これを掘り下げる時間はありませんでした。上記のように、、およびを実装するsind()cosd()、次のtand()ケース例の表に到達します。

SIND
 angle value 
  -540 -0
  -360 -0
  -180 -0
     0  0
   180  0
   360  0
   540  0

COSD
 angle value
  -630  0
  -450  0
  -270  0
   -90  0
    90  0
   270  0
   450  0

TAND
 angle value
  -540  0
  -360 -0
  -180  0
     0  0
   180 -0
   360  0
   540 -0

5

sin()とtan()は通常、与えられた符号ゼロ入力に対して同じ符号ゼロ結果を返します

それは一般的には真実である可能性があります:

  • 速度/精度。十分に小さいダブルの場合、最良の答えはsin(x)ですx。つまり、約より小さい数値の場合1.49e-8、xの正弦に最も近いdoubleは実際にはx自体です(sin()のglibcソースコードを参照)。

  • 特殊ケースの取り扱い

    いくつかの異常な算術演算は、ゼロの符号の影響を受けます。たとえばです"1/(+0) = +inf""1/(-0) = -inf"。その有用性を維持するために、符号ビットは、連続性の考慮事項から導出されたルールに従って、特定の算術演算を通じて伝播する必要があります。

    IEEE標準では指定されていませんが、sin(z)やtan(z)などの基本的な超越関数の実装とその逆関数および双曲線アナログは、同様の規則に従うことが期待されています。の実装でsin(z) は、の符号とz その値を再現することが期待されていますz = ±O

    (W. Kahanによる複雑な初等関数または何もないことについての多くのやり直しのための分岐カット

    負の符号のゼロは、片側制限として下から0に近づくという数学的分析の概念に反響します(考慮1 / sin(x):ゼロの符号は大きな違いを生みます)。

編集

2番目の点を考慮して、次のように記述my_sindします。

my_sind(-0.0) is -0.0
my_sind(0.0) is 0.0

最新のC標準(F.10.1.6 sinおよびF.10.1.7 tan、符号付きゼロの実装)は±0、引数がの場合、変更されずに返されることを指定しています。

編集2

他の値については、近似の問題だと思います。与えられましたM_PI<π:

0 = sin(π) < sin(M_PI)  1.2246467991473532e-16  +0.0
0 = sin(-π) > sin(-M_PI)  -1.2246467991473532e-16  -0.0
0 = sin(2*π) > sin(2*M_PI)  -2.4492935982947064e-16
0 = sin(-2*π) < sin(-2*M_PI)  2.4492935982947064e-16

したがってmy_sind、180°の倍数で正確な回答が得られた場合、それは戻る+0.0か、または-0.0(どちらか一方を優先する明確な理由はわかりません)。

my_sindが何らかの近似(例:degree * M_PI / 180.0変換式)を使用する場合、それが臨界値にどのように近づいているかを検討する必要があります。


あなたはどう思いsind(180), sind(-180), sind(360), sind(-360),...ますか?
chux-モニカを2014年

更新していただきありがとうございます。多分私の投稿は明確ではありません。主な質問は、そうでないときにmy_trig(x)戻る必要がありますか?-0.0|x|0.0
chux-モニカを2014年

「my_sindが180°の倍数で正確な回答を提供する場合、+ 0.0または-0.0を返す可能性があります(どちらか一方を優先する明確な理由はわかりません)。」これは、これまでのところ最も近い議論のポイントです。「最小の驚きの原則」は常に戻ることを奨励すると思いますが+0.0-0.0(以外のx == +/-0.0)状況によっては、やむを得ない理由があるかどうかを調べます。
chux-モニカを2014年

@chux:の倍数の180.0場合、実際には、これらの値を指定して相対的なマシン精度の値を調べる必要があると思います。つまり、その数値形式で異なる表現可能な値を与える最小の増分/減分です。次に、その値を真の値と比較して、プラス側にあるかマイナス側にあるかを確認します。
2015年

@rwongアイデアをありがとう。90.0の倍数正確な sind(double degrees)cosd(double degrees)値を返すことができます:-1.0, +0.0, +1.0。この投稿は-0.0(sind(-0.0)を除いて)返されるはずです。注:sind()は単純なアプローチを使用しませsin(x/360*M_PI)
chux-モニカを2015年

3

ライブラリは+0と-0を区別しようとしません。IEEE 754はこの違いについてかなり心配しています...私は関数(math.h内)が何もない兆候についてわざわざ書くことなく書くにはかなり難しいことに気づきました。-PJ Plauger、標準Cライブラリ、1992年、128ページ。

正式には、trig関数はC標準に準拠してゼロの符号を返す必要があります...動作は未定義のままです。

未定義の動作に直面した場合、最小の驚きの原則は、対応する関数の動作をから複製することを示唆していmath.hます。これは正当なmath.h匂いですが、ゼロの符号に依存するコードにバグを正確に導入する方法のように、匂いの対応する関数の動作から逸脱します。


math.h+/- pi / 2や+/- piなどの引数が指定されている場合、これらの関数は+/- pi / 2などに近い表現可能な値しか取得できないため、のトリガー関数は0.0を返しません。これらの「近い」値は0.0に近い結果を返します。stdライブラリのトリガー関数(sin cos tan)は、入力(+/- 0.0を除く)に対して0.0(または-0.0)を返しませんが、my_sind()、my_cosd()、my_tand()は0.0(または-0.0)を返すことができるため、複製する0.0の動作はありません。
chux-モニカを2014年

@chux sin(-0.0)戻るべき前提-0は疑わしいです。IEEE標準の実装の詳細を三角法の原理として扱います。IEEE実装で具現化された2つの間隔の限界としてゼロという一般的な数学的原理がありますが、それは一般的な三角法の範囲内ではない抽象化のレベルで発生します[したがって、三角関数が返すもののばらつき]。起こり得る最良の方法は、任意の規則を定義できることですがmath.h、ゼロの符号を介してのの不平等とは異なります。
ベンラジャーズ2014年

注:をsin(-0.0)返すことをお勧めしません-0.0が、がとmy_sind(x)一致sin(x)する必要xがあり+/-0.0ます。IOW:以前のプラクティスに従います。さらに、問題自体は、ときに何をすべきかについての詳細であるx != 0.0必要があり、my_sind(x)これまでに返す-0.0のようにmy_sind(180)など、?多分あなたの答え/コメントはそれに対処します-しかし、私はそれを見ていません。
chux-モニカを2014年

@chux動作が未定義の場合、未定義です。それがCのやり方です。プラウガーは、20年前に書いたときと+0比べて心配していませんでした。違いについてのフレッチングがどのような問題を解決しているかは、はっきりしません。-0math.h
ベンラジャーズ2014年

1
うまくいけば、piが非合理的であるため、適切に実装さsin(rad)れた任意の値rad>0および任意の精度の結果が得0.0られることはありません。[参考文献]は(www.csee.umbc.edu/~phatak/645/supl/Ng-ArgReduction.pdf)がしかしmy_sind(deg)正確得られる0.0(+または- )のすべての倍数180.0値0.0は、正しい数学的結果です。「最小驚きの原則」は、これらの場合に0.0を返すことを示唆しています。私の質問は-0.0、これらの場合に返される必要がありますか?
chux-モニカを2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.