
C++でdouble以上の精度で計算できるクラスを作って、現在数学関数を作成中なのですが三角関数関連のところでつまずいてしまいました
sin,cosについてはテイラー展開を使って差分が一定以下になるまで次数をどんどん高くしていくという方法で算出したのですが
tanの展開公式が複雑すぎて計算量が多くなり時間がかかりすぎてしまいます。(特にベルヌーイ数の算出)
また|x|≧1についてのarctan(x)の算出方法もわかりません。
tanのより簡単な算出方法、|x|≧1でのarctan xの算出方法を教えていただけないでしょうか?
また、テイラー展開よりもっと簡単な算出方法があればそれも教えていただけるとありがたいです。
なお、精度の関係上標準関数(tan(x),atan(x)など)は使いません。
No.2ベストアンサー
- 回答日時:
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 で計算してもそれほど誤差は大きくならないような気がします. この辺は「やってみないとわからない」世界かもしれませんが.
ん~, 数値計算の本はどこかになかったかなぁ....
再び早速のご回答ありがとうございます。
arctanについては、
・√演算の精度が満足なレベルであることを確認している
・πの値についてはWeb上にあった記述から数百桁程度をそのまま流用
ということでとりあえずはこの方法で進めたいと思います。
(勿論、より良い方法があるならば教えていただきたいと思います。)
tanについてはとりあえず確認した範囲では、ほとんどの場合はsin,cosと同程度の精度のようです
ただ、|x|=π/2近傍については仰るとおり近ければ近いほど誤差が大きくなってしまうようです
発散してしまう関係上仕方ないのかもしれませんが、とりあえず引き続きsin/cos以外の方法を募集したいと思います。
No.4
- 回答日時:
ちょい待った.
「差分」?
浮動小数を使うなら, 普通は相対誤差で評価しませんか?
ちなみに tan の方は, double で計算すると 9~10項あれば十分で, それ以上は精度が出ないようです. 真値との相対誤差は, 10項でだいたい 49bit 程度. 連分数展開で 1項増やすと 4~5bit 程度精度がよくなるような感じです.
返事が遅れてしまい申し訳ありませんでした
差分の件ですが、他の関数でテイラー展開において有効桁の範囲で変化がなくなった時点でループ終了という処理を行っていたのでそのような表現になりました。
連分数展開を行った際、どの程度の項で十分な精度を確保できるのかがわからずとりあえず多めに項をつけていたのですが、
>真値との相対誤差は, 10項でだいたい 49bit 程度. 連分数展開で 1項増やすと 4~5bit 程度精度がよくなるような感じです
とのことなので、これを参考に減らし、速度が大分向上しました
結論としてはarctanは問題なく
tanも問題はないものの、計算量と精度を考慮するとsin/cosの方が効率として良い様なのでこちらの方で計算することにしました。
とりあえず、これで三角関数についての質問を締切りたいと思います。
お付き合いいただきまことにありがとうございました。
No.3
- 回答日時:
高精度数値計算の本が手元にないので適当に検索したんですが, arctan については連分数展開をするという方針もあるみたいですね. 確かに多項式で計算するよりも有理式で計算する方が精度がよくなる傾向はあるようなので, 考えられる方法ではあります.
tan は... う~ん.... こっちも連分数展開する? 「理科年表にある」という情報を見付けたので見てみると
tan x = x / (1 - x^2 / (3 - x^2 / (5 - x^2 / (7 - ...))))
と書かれてるなぁ.
この回答への補足
とりあえず確認できる範囲ではarctanについてはこちらの方が若干精度が高いようです(ほぼ同じともいえますが)
ただ、連分数展開の関係上差分が一定以下になるまで繰り返すという方法が使えないので
どうにも強制的に何回展開するのかを指定して計算せねばならず
テイラー展開より少々遅くなってしまうようです
tanについては時間がないのでまた後日(といっても年明けになりそうですが)確認いたします
No.1
- 回答日時:
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についてより効率的・高精度なものがあればそれも教えていただきたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VB6.0での小数点の扱いについて
-
c languageで 簡単な質問があ...
-
ExcelでPC(パソコン)によって...
-
ExcelのINT関数の計算結果がお...
-
浮動小数演算は実行環境の変化...
-
Log関数に関する質問
-
三菱シーケンサ(Aシリーズ)で...
-
”/”を使わずに割り算したいんで...
-
VBAでミリ秒まで出力する方法
-
時刻の比較
-
EXCELの関数"STDEV(標準偏差)"...
-
計算の丸め誤差の解消について
-
O(n log n)について2
-
三角比の俯角の計算
-
Double型について
-
最早開始時間と最遅完了時刻を...
-
Aの値からBの値を除するとは??
-
信頼区間の1.96や1.65ってどこ...
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語 エラーの原因がわからな...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
有効数字について 以前質問をし...
-
c languageで 簡単な質問があ...
-
EXCELの関数"STDEV(標準偏差)"...
-
ExcelでPC(パソコン)によって...
-
三菱シーケンサ(Aシリーズ)で...
-
floatの有効桁数
-
255の2の補数、B'00000001'が-...
-
O(n log n)について2
-
符号誤り率の計算は例題でどの...
-
CRCの計算方法について
-
VB.net Double と...
-
コンピューターは指数関数をど...
-
16進数 加算 減算 C言語
-
ExcelのINT関数の計算結果がお...
-
C言語でセルオートマトンを作成...
-
BCD・HEX・BINについて
-
”/”を使わずに割り算したいんで...
-
三角比の俯角の計算
-
除算を使わずに10で割りたい。
-
VBAでミリ秒まで出力する方法
おすすめ情報