Sinテーブルを使った逆三角関数の値の出し方

このQ&Aのポイント
  • Sinテーブルとテイラー展開を用いて、Sin、Cos、Tanの近似値を求めることができます。
  • しかし、Sinテーブルから直接逆三角関数の値を求める方法については、標準関数を使う方法が一般的です。
  • Sinテーブルを使用して逆三角関数の値を求める方法については、詳細な情報はほとんど見つかりませんでした。
回答を見る
  • ベストアンサー

Sinテーブルの値からAtan等の値の出し方

Sinテーブルを使い Atanの値を出す方法を探したのですが 方法が見つかりませんでしたので質問します 使用言語はC++です 次のようなSinテーブルがあるとします 大きさは901で0~90度までの値を分割して入れてある データ型はdouble テーブル引きの結果にSin、Cosの値を使った テイラー展開を用いて誤差を小さくしている 以下のサイトのSinテーブルを参考にしています http://ctrlwww.ee.noda.tus.ac.jp/wiki/kansai/index.php/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0%E3%81%AE%E9%AB%98%E9%80%9F%E5%8C%96 上記のSinテーブルを使うことで Sin、Cos、Tanの近似値が出せる状態から Asin、Acos、Atanの値を出す方法はあるでしょうか 標準関数を使えばいいと言われてしまえばそこで終わりですが せっかくSinテーブル+テイラー展開による補正で相応の精度で値を出せるのなら 逆三角関数の値をこれを使って出せないかと考えました いろいろとサイトを回りましたが ほとんどが標準関数を使っての物だったので もし方法があるのならお答えいただけるとありがたいです

noname#231246
noname#231246

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

x とか y とかがなんのことなのかわからないのですが, とりあえず atan x を求めたいなら y = x/√(x^2+1) で求まる y を sin のテーブルから探せばよいということになります. で, その URL に「平方根の逆数」を求めるアルゴリズムがあるので, そいつを使えば除算を乗算に置き換えることができるはず. 誤差はよくわからんけど, 気になるならニュートン法を一発かませばいいような気がする.

noname#231246
質問者

お礼

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

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

あ, sin のテーブルがあるときに atan を計算したいってことね. y = tan x のとき sin x = y/√(y^2+1) と sin に変換すればいいってことにはなる... けど, なんか平方根と除算がくやしい. 工夫すれば除算の代わりに乗算にできたような気もするけど忘れた. この辺はハードウェアがどこまでサポートしてるかにもよるかな? 直接的には atan のテーブルを持ちそうだけど, sin や cos と違って tan は値域に制限がないので, atan のテーブルの大きさをどうするかという問題が発生する. もちろんがんばればいいんだけどかえって tan のテーブルから探索した方が速い可能性すらある.

noname#231246
質問者

お礼

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

noname#231246
質問者

補足

平方根に関して言えば このURL先にある方法で少しだけでも高速化はできそうです http://www001.upp.so-net.ne.jp/y_yutaka/labo/math_algo/math_algo.html 除算に関しては難しいところですね 今回の場合は yの値をx/yの結果として y/√(y^2+1)を サインテーブルの引数に 入れればいいということでいいのでしょうか? 自分の理解力が無いのが悪いのですが このあたりの回答もあるとありがたいです

  • ki073
  • ベストアンサー率77% (491/634)
回答No.4

テーブルから検索する方法ですが、 tanθ=sinθ/cosθ でtanθのテーブルを作ります。-90~90度の範囲では単調増加の関数になりますので(対称なので0から90でよい)、二分探索などで探せばそこそこの速度がでます。 参考 http://ja.wikipedia.org/wiki/二分探索 更に速くしたいのでしたら、atanのテーブルを作ってしまうか、荒いatanテーブルを作って、tanのテーブルを引き始める場所が分かるようにします。 ピッタリの値はまず無いので、前後の値を使って補間します、直線補間が簡単なのですが、二次関数程度がそこそこの精度がでるはずです。 参考 http://ja.wikipedia.org/wiki/内挿

  • ki073
  • ベストアンサー率77% (491/634)
回答No.3

そのままのテーブルを使うとなると、逆関数の場合はテーブルの計算値から探し出さないとならないので、効率は悪くなります。 幸いどれも単調な関数ですので、単調増加あるいは単調減少になっていますので、探し方を工夫すればそれなりの速くはなります。 それよりも同じように逆関数のテーブルを作る方が速度は稼げます。 昔のCPUが遅い時代にはテーブルから値をとってくる方法が結構行われていました。 最近のCPUは計算は速いが、メモリアクセスそれに比べて極端に遅いし、テーブル引きの場合にはベクトル化をやりにくいので、あまりメリットがないように思います。一度比べてみられてはいかがでしょうか。 精度、速度ともに興味深い結果になるかも知れません(私も興味があります) コンパイラに備わっている関数はベクトル化が可能で十分な精度が出るように思うのですが、どうなんでしょうか。

noname#231246
質問者

補足

確かに最近のCPUは性能が良いですが ハードによってまちまちだと思います 一口にCPUと言ってもデスクトップ、ノート、スマホ、etc・・・とありますしね なのでメリットは現在でもしっかりとある、と考えています 速度計測はすでに行いましたが あまり変わらなかったという結果でした、が あくまでも自分の環境の話です 他の方の環境でも同じとは限らないと考えてます 今回の質問は sinテーブルからatanの値を出せないか? そして、具体的な式や方法は?結果はどうなるのか? といった疑問を解消するためですので ベクトル化などに関しては考えていません

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

工夫はできるけど #1 同様「表から探し出す」くらいかな. テイラー展開も入れる?

noname#231246
質問者

お礼

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

noname#231246
質問者

補足

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

  • tsunji
  • ベストアンサー率20% (196/958)
回答No.1

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

noname#231246
質問者

お礼

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

関連するQ&A

  • アークタンジェントテーブルの誤差補正方法について

    下記のサイトのソースを元に アークタンジェント( atan2()関数 )をテーブル化してみたのですが http://asdf.wkeya.com/code/usetable_hpp.html 誤差が気になり何か良い補正の方法はないかと探して見たところ なかなか見つかりませんでした 次のサイトでSinテーブルの誤差を修正する方法は見つけたのですが http://ctrlwww.ee.noda.tus.ac.jp/wiki/kansai/index.php/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0%E3%81%AE%E9%AB%98%E9%80%9F%E5%8C%96 そこでatanテーブルの誤差を補正する なにかわかりやすくよい方法はないでしょうか?

  • sin ,cos

    sinα+sinβ=1,cosα+cosβ=0のときcos(α-β)の値をどのように求めるかわかりません cos(α-β)を加法定理で展開すると cosαcosβ+sinαsinβ となりますが どのように求めるかわかりません。 おねがいします

  • atan2関数 ベクトル計算・・・

    atan2関数を使用した、ベクトルとベクトルのなす角度を 返す関数 というのを作りたいのですが、いいプログラム例があればご紹介ください。 また、 ベクトルの視点を中心として、 angle(rad) 回転させる 関数について。  回転公式 (x, y) を angle(rad) 回転 → (x', y')  x' = cos(angle)*x + sin(angle)*y  y' = -sin(angle)*x + cos(angle)*y どちらかひとつでも、お分かりになる方がいらしたらよろしく御願いします。

  • SINとCOSのフーリエ変換(というか位相差の出し方)

    SINの各角度ごとの値:S(K) (K=1~360) COSの各角度ごとの値:C(K) (K=1~360) 周波数とサンプリング時間とデータの数をf、ts、 X(K)=S(K)*COS(2π*K/360)  Y(K)=S(K)*SIN(2π*K/360) Σ(K=1~360)X(K)=X Σ(K=1~360)Y(K)=Y ATAN(Y/X)=SIN関数の位相 になると今、思っています そしてS(K)の所をC(K)に変えればCOS関数の位相が出ると思っています。 そして二つの関数の位相差は90度のはずですが 二つとも-90度ぐらいで位相差はほぼ0になってしまいます。どこが違うのでしょうか?

  • sinα+cosα=sinαcosα

    sinα+cosα=sinαcosαのとき、sinα+cosαの値を求めるにはどうすればいいですか? 問題では2元連立方程式で解けとなっています。 まったくわからないので教えていただけませんか? ちなみに三角関数では解けました............

  • sinの値を求めるプログラムでお聞きします。

    cos(x)の値をcosのテーラー展開の式から求めるプログラムを作り、無限級数の項の絶対値が0.00001以下になったら打ち切って、コンピュータで定義されるcos(x)の値との差を 0.0≦x≦0.1 の範囲で0.01刻みに求めよ。ただし、結果はファイルに書き出すこと。 という問いがあり、プログラムは下記のようなものだったのですが、 #include <stdio.h> #include <math.h> double COS(double x); int main(void) { double a; FILE *fout; fout=fopen("file1.txt","w"); for(a=0;a<0.1;a=a+0.01) { fprintf(fout,"a=%f COS=%e cos=%e error=%e\n",a,COS(a),cos(a),COS(a)-cos(a)); } return 0; } double COS(double x) { double t; double y; int n; y=1.0; t=1.0; n=1; while(1) { t=-t*x*x/((2*n)*(2*n-1)); if(fabs(t)<=0.00001) break; y=y+t; n++; } return y; } これが、例えば、cos(x)ではなくsin(x)についてだった場合、上記の最初に書いてある条件もまったく同じでプログラムを作ったとすると、上記のプログラムのどこどのように変えればいいのでしょうか。 分からなくて困っています。助けてください。

  • sinの値を求めるプログラムで質問です。

    sin(x)の値を求めるプログラムで質問です。 cos(x)の値をcosのテーラー展開の式から求めるプログラムを作り、無限級数の項の絶対値が0.00001以下になったら打ち切って、コンピュータで定義されるcos(x)の値との差を 0.0≦x≦0.1 の範囲で0.01刻みに求めよ。ただし、結果はファイルに書き出すこと。 という問いがあり、プログラムは下記のようなものだったのですが、 #include <stdio.h> #include <math.h> double COS(double x); int main(void) { double a; FILE *fout; fout=fopen("file1.txt","w"); for(a=0;a<0.1;a=a+0.01) { fprintf(fout,"a=%f COS=%e cos=%e error=%e\n",a,COS(a),cos(a),COS(a)-cos(a)); } return 0; } double COS(double x) { double t; double y; int n; y=1.0; t=1.0; n=1; while(1) { t=-t*x*x/((2*n)*(2*n-1)); if(fabs(t)<=0.00001) break; y=y+t; n++; } return y; } これが、例えば、cos(x)ではなくsin(x)についてだった場合、上記の最初に書いてある条件もまったく同じでプログラムを作ったとすると、上記のプログラムのどこを変えればいいのでしょうか。どなたか教えてください。

  • 三角関数、逆三角関数の算出方法がわかりません

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

  • sin(π)が0にならないです

    C言語でsin(π)の値を出したいのですが0になりません。 1.224647e-16という値が出てきます。 sin(M_PI)と入力しています。 これを何とか0にする方法はないでしょうか? ご回答お願い致します。

  • 教えてください。

    関数f(θ)=acos^2θ+(a-b)sinθcosθ+bsin^2θの最大値が3+√7 、最小値が3-√7 となるような実数の定数a,bの値を求めよ。 解いてくださるとうれしいです。よろしくお願いします。

専門家に質問してみよう