プロが教える店舗&オフィスのセキュリティ対策術

C++でdouble以上の精度で計算できるクラスを作って、現在数学関数を作成中なのですが三角関数関連のところでつまずいてしまいました
sin,cosについてはテイラー展開を使って差分が一定以下になるまで次数をどんどん高くしていくという方法で算出したのですが
tanの展開公式が複雑すぎて計算量が多くなり時間がかかりすぎてしまいます。(特にベルヌーイ数の算出)
また|x|≧1についてのarctan(x)の算出方法もわかりません。
tanのより簡単な算出方法、|x|≧1でのarctan xの算出方法を教えていただけないでしょうか?
また、テイラー展開よりもっと簡単な算出方法があればそれも教えていただけるとありがたいです。
なお、精度の関係上標準関数(tan(x),atan(x)など)は使いません。

A 回答 (4件)

arctan x は tan π/8 = √2-1 を使って,


tan (θ-π/8) = (tan θ - (√2-1)) / (1 + (√2-1) tan θ) から
arctan x = arctan [(x - (√2-1)) / (1 + (√2-1)x)] + π/8
とする方法はあったような気がします. つまり, |x| < 0.42 なら普通に arctan の展開級数を使い, 0.42 ≦ |x| ≦ 1 ならこの式で小さくする, と. √2-1 とか π/8 を高精度に計算できないと無意味ですが.
tan x の方は... ん~, どうなんでしょうねぇ. どうしても x が π/2 に近いと誤差は大きくなりますが, 相対誤差そのものは分子と分母の相対誤差の和程度なので, sin x / cos x で計算してもそれほど誤差は大きくならないような気がします. この辺は「やってみないとわからない」世界かもしれませんが.
ん~, 数値計算の本はどこかになかったかなぁ....
    • good
    • 0
この回答へのお礼

再び早速のご回答ありがとうございます。

arctanについては、
・√演算の精度が満足なレベルであることを確認している
・πの値についてはWeb上にあった記述から数百桁程度をそのまま流用
ということでとりあえずはこの方法で進めたいと思います。
(勿論、より良い方法があるならば教えていただきたいと思います。)

tanについてはとりあえず確認した範囲では、ほとんどの場合はsin,cosと同程度の精度のようです
ただ、|x|=π/2近傍については仰るとおり近ければ近いほど誤差が大きくなってしまうようです
発散してしまう関係上仕方ないのかもしれませんが、とりあえず引き続きsin/cos以外の方法を募集したいと思います。

お礼日時:2007/12/26 17:53

ちょい待った.


「差分」?
浮動小数を使うなら, 普通は相対誤差で評価しませんか?
ちなみに tan の方は, double で計算すると 9~10項あれば十分で, それ以上は精度が出ないようです. 真値との相対誤差は, 10項でだいたい 49bit 程度. 連分数展開で 1項増やすと 4~5bit 程度精度がよくなるような感じです.
    • good
    • 0
この回答へのお礼

返事が遅れてしまい申し訳ありませんでした
差分の件ですが、他の関数でテイラー展開において有効桁の範囲で変化がなくなった時点でループ終了という処理を行っていたのでそのような表現になりました。
連分数展開を行った際、どの程度の項で十分な精度を確保できるのかがわからずとりあえず多めに項をつけていたのですが、
>真値との相対誤差は, 10項でだいたい 49bit 程度. 連分数展開で 1項増やすと 4~5bit 程度精度がよくなるような感じです
とのことなので、これを参考に減らし、速度が大分向上しました

結論としてはarctanは問題なく
tanも問題はないものの、計算量と精度を考慮するとsin/cosの方が効率として良い様なのでこちらの方で計算することにしました。

とりあえず、これで三角関数についての質問を締切りたいと思います。
お付き合いいただきまことにありがとうございました。

お礼日時:2008/01/07 12:24

高精度数値計算の本が手元にないので適当に検索したんですが, arctan については連分数展開をするという方針もあるみたいですね. 確かに多項式で計算するよりも有理式で計算する方が精度がよくなる傾向はあるようなので, 考えられる方法ではあります.


tan は... う~ん.... こっちも連分数展開する? 「理科年表にある」という情報を見付けたので見てみると
tan x = x / (1 - x^2 / (3 - x^2 / (5 - x^2 / (7 - ...))))
と書かれてるなぁ.

この回答への補足

とりあえず確認できる範囲ではarctanについてはこちらの方が若干精度が高いようです(ほぼ同じともいえますが)
ただ、連分数展開の関係上差分が一定以下になるまで繰り返すという方法が使えないので
どうにも強制的に何回展開するのかを指定して計算せねばならず
テイラー展開より少々遅くなってしまうようです

tanについては時間がないのでまた後日(といっても年明けになりそうですが)確認いたします

補足日時:2007/12/27 17:48
    • good
    • 0

tan x は sin x / cos x で計算した方が速かったりして.


あと, |x| > 1 に対する arctan x は高精度にπを作る方法を別途用意して
arctan x = π/2 - arctan (1/x)
から計算することが多いんじゃないかなぁ? もっとも, |x| が 1 に近いとやっぱり収束が遅いのでもっと小さな値に変換しておくことも多いと思います.

この回答への補足

早速のご回答ありがとうございます。
tanx=sinx/cosxについては
確かに一番それが手っ取り早いのですが、誤差が大きくなりそうな気がするので
(もっともベルヌーイ数の誤差がどうにも大きすぎるようなので普通のテイラー展開を使うよりは誤差はないようですが)
もう少し他の方法を募集いたします。

arctan xについては|x|=1近傍以外ではこれが手っ取り早そうなのでこれを使わせていただきます。
引き続き|x|=1近傍に関して良い方法があれば教えてください。
もちろん∀xについてより効率的・高精度なものがあればそれも教えていただきたいと思います。

補足日時:2007/12/26 15:55
    • good
    • 0
この回答へのお礼

お礼と補足を間違えました、すいません。
改めてご回答ありがとうございました。

お礼日時:2007/12/26 16:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!