アプリ版:「スタンプのみでお礼する」機能のリリースについて

Sinテーブルを使い
Atanの値を出す方法を探したのですが
方法が見つかりませんでしたので質問します

使用言語はC++です

次のようなSinテーブルがあるとします
大きさは901で0~90度までの値を分割して入れてある
データ型はdouble

テーブル引きの結果にSin、Cosの値を使った
テイラー展開を用いて誤差を小さくしている

以下のサイトのSinテーブルを参考にしています
http://ctrlwww.ee.noda.tus.ac.jp/wiki/kansai/ind …

上記のSinテーブルを使うことで
Sin、Cos、Tanの近似値が出せる状態から
Asin、Acos、Atanの値を出す方法はあるでしょうか

標準関数を使えばいいと言われてしまえばそこで終わりですが
せっかくSinテーブル+テイラー展開による補正で相応の精度で値を出せるのなら
逆三角関数の値をこれを使って出せないかと考えました

いろいろとサイトを回りましたが
ほとんどが標準関数を使っての物だったので
もし方法があるのならお答えいただけるとありがたいです

A 回答 (6件)

x とか y とかがなんのことなのかわからないのですが, とりあえず


atan x
を求めたいなら
y = x/√(x^2+1)
で求まる y を sin のテーブルから探せばよいということになります.

で, その URL に「平方根の逆数」を求めるアルゴリズムがあるので, そいつを使えば除算を乗算に置き換えることができるはず. 誤差はよくわからんけど, 気になるならニュートン法を一発かませばいいような気がする.
    • good
    • 0
この回答へのお礼

ごめんなさい
トラブルで長期間ネットに繋げない状態でした
回答ありがとうございます
とりあえず教えて頂いた方法を使って
なんとかしてみようと思います。

お礼日時:2013/02/22 04:30

あ, sin のテーブルがあるときに atan を計算したいってことね.



y = tan x のとき sin x = y/√(y^2+1) と sin に変換すればいいってことにはなる... けど, なんか平方根と除算がくやしい. 工夫すれば除算の代わりに乗算にできたような気もするけど忘れた. この辺はハードウェアがどこまでサポートしてるかにもよるかな?

直接的には atan のテーブルを持ちそうだけど, sin や cos と違って tan は値域に制限がないので, atan のテーブルの大きさをどうするかという問題が発生する. もちろんがんばればいいんだけどかえって tan のテーブルから探索した方が速い可能性すらある.

この回答への補足

平方根に関して言えば
このURL先にある方法で少しだけでも高速化はできそうです
http://www001.upp.so-net.ne.jp/y_yutaka/labo/mat …

除算に関しては難しいところですね

今回の場合は
yの値をx/yの結果として

y/√(y^2+1)を

サインテーブルの引数に
入れればいいということでいいのでしょうか?

自分の理解力が無いのが悪いのですが
このあたりの回答もあるとありがたいです

補足日時:2012/12/13 15:49
    • good
    • 0
この回答へのお礼

回答ありがとうございます
sinテーブルからのatanの求め方があるというのだけでも
ありがたいです

お礼日時:2012/12/13 15:08

テーブルから検索する方法ですが、


tanθ=sinθ/cosθ
でtanθのテーブルを作ります。-90~90度の範囲では単調増加の関数になりますので(対称なので0から90でよい)、二分探索などで探せばそこそこの速度がでます。
参考
http://ja.wikipedia.org/wiki/二分探索

更に速くしたいのでしたら、atanのテーブルを作ってしまうか、荒いatanテーブルを作って、tanのテーブルを引き始める場所が分かるようにします。
ピッタリの値はまず無いので、前後の値を使って補間します、直線補間が簡単なのですが、二次関数程度がそこそこの精度がでるはずです。
参考
http://ja.wikipedia.org/wiki/内挿
    • good
    • 1

そのままのテーブルを使うとなると、逆関数の場合はテーブルの計算値から探し出さないとならないので、効率は悪くなります。


幸いどれも単調な関数ですので、単調増加あるいは単調減少になっていますので、探し方を工夫すればそれなりの速くはなります。
それよりも同じように逆関数のテーブルを作る方が速度は稼げます。

昔のCPUが遅い時代にはテーブルから値をとってくる方法が結構行われていました。

最近のCPUは計算は速いが、メモリアクセスそれに比べて極端に遅いし、テーブル引きの場合にはベクトル化をやりにくいので、あまりメリットがないように思います。一度比べてみられてはいかがでしょうか。
精度、速度ともに興味深い結果になるかも知れません(私も興味があります)

コンパイラに備わっている関数はベクトル化が可能で十分な精度が出るように思うのですが、どうなんでしょうか。

この回答への補足

確かに最近のCPUは性能が良いですが
ハードによってまちまちだと思います
一口にCPUと言ってもデスクトップ、ノート、スマホ、etc・・・とありますしね
なのでメリットは現在でもしっかりとある、と考えています
速度計測はすでに行いましたが
あまり変わらなかったという結果でした、が
あくまでも自分の環境の話です
他の方の環境でも同じとは限らないと考えてます

今回の質問は
sinテーブルからatanの値を出せないか?
そして、具体的な式や方法は?結果はどうなるのか?
といった疑問を解消するためですので
ベクトル化などに関しては考えていません

補足日時:2012/12/10 08:45
    • good
    • 0

工夫はできるけど #1 同様「表から探し出す」くらいかな.



テイラー展開も入れる?

この回答への補足

そうですね
出来ればテイラー展開などを使って
ある程度の誤差修正ができるとありがたいです
自分は参考先のソースを改変して
テーブルの規模、テイラー展開の項数の指定などを
組み込んでいますので出来れば揃えたいと考えています

補足日時:2012/12/10 08:34
    • good
    • 0
この回答へのお礼

回答有り難うございます
やはりatanテーブルからのルックアップになるのでしょうか?

お礼日時:2012/12/10 08:32

値とテーブルを比較して近似値の配列番号を取り出すしか方法は無いね。

    • good
    • 0
この回答へのお礼

回答ありがとうございます
sinテーブルではなくてatanのテーブルで
行うということで合っているでしょうか?

お礼日時:2012/12/10 08:32

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