自作関数シリーズ第2回 sin関数 (C言語、Java、Python、Ruby)
このシリーズは普段ライブラリを利用して求めているような計算を自作するとしたらどのようなコードになるのかを紹介するシリーズです。といってもOpenCVやBeautiful Soupのような大規模なライブラリの関数を自作するわけではありません。大規模なライブラリは眺めてこんな感じ何だなって理解するに留めて、素直に作ってくれた人に感謝して利用しましょう。さて第2回ではsinを求める関数を自作したいと思います。ちなみに普通にsinを求めるには
C言語: include<math.h>をしてからsin関数を使う
Java: Mathクラスのsinメソッドを使う
Python: import mathをしてsin関数を使う
Ruby: Math.sinを使う
自作関数シリーズ第1回(ルートを求める関数)
https://koro-game-programming.hatenablog.com/entry/2019/12/31/205914
さて、ます今回sinを求めるにあたって使う数学的な知識から入ります。今回sinを求めるのにはマクローリン展開という方法を使います。
これは下のような式で表される展開です。大学で理系の方なら少なくとも一度は聞いたことあると思います。
そしてf(x) = sin(x)として上の式に代入した結果が下のようになります。
この式を元に実際にsinを求めるプログラムを書いてみると下のようになります。ちなみにコンピューターに無限回計算させるわけにもいかないので、今回はxの19乗の項までの近似計算としています(この程度のループでもかなり良い精度となる)。ちなみに今回は変数sumを第n項までの合計を保存するための変数、tを各項を求める変数としています。そしてまずtとsumにxを代入、次にtに
-(x*x)/( (i*2)*(i*2+1) )をかけることで-x^3/3!を求め、それをsumに加えます。さらにこの操作を第10項目まで繰り返しています。
C言語版
double my_sin(double x){
double sum = x;
double t = x;
int i;
for(i=1;i<10;i++){
t *= -(x*x)/( (i*2)*(i*2+1) );
sum += t;
}
return sum;
}
Java版
public static double my_sin(double x){
double sum = x;
double t = x;
for(int i=1;i<10;i++){
t *= -(x*x)/( (i*2)*(i*2+1) );
sum += t;
}
return sum;
}
def my_sin(x):
sum = x
t = x
for i in range(1,10):
t *= -(x*x)/( (i*2)*(i*2+1) )
sum += t
return sum
Ruby版
def my_sin(x)
sum = x
t = x
for i in 1..10 do
t *= -(x*x)/( (i.to_f*2)*(i.to_f*2+1) )
sum += t
end
return sum
end
ちなみにマクローリン展開を使うことでcos,tan,log(1-x),exp(x)なども近似的に簡単に求めることができるので気になったら作ってみてください。