Swiftでsinxの近似値を求める

公開:2020/10/14
更新:2020/10/14
3 min読了の目安(約2700字TECH技術記事

なぜSwiftなの?

Swiftは環境構築などする必要がなく,MacかiPadがあればPlaygroundsをインストールするだけで使うことができる。
また,Playgroundsにはステップ実行ゆっくり実行という機能があり,for文やwhile分をステップごとに実行し,実行されている時の値の変化を確認することもできる。
さらに,ビューア機能を使えば変数の変化の様子を勝手にグラフ表示してくれる。
2020-10-14 11.16のイメージ.jpg

sinxのマクローリン展開

sinxsinxをマクローリン展開すると,

sinx=xx33!+x55!x77!++(1)n1x2n1(2n1)!+ sinx = x - \frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+⋯+\frac{(-1)^{n-1}x^{2n-1}}{(2n-1)!}+⋯

と表されるのであった。この記事ではsinxsinxの近似値をプログラミングを使って求めていく。(言語はSwift)ipadでも大丈夫。

1.変数を用意する

マクローリン展開は何回でも微分できる関数f(x)f(x)xxの冪乗関数の級数の展開式の和で近似させるものであるのであった。この記事ではsinxsinxの値をsumとして,sumにだんだん値を加えていく。

var sum = 0
print(sum)    //0
sum += 1
print(sum)    //1

また,近似するxxを入れる定数も用意しなければならない。この時近似する値としてπ/6\pi/6π/3\pi/3などの値を用いたいので,π\piが使えるようimport Foundationを書いておく。

import Foundation
var sum = 0
let x = Double.pi/2

さらに,項として更新され続ける変数を用意する。

var item = x

第一項は定数と同じになるので,xを入れておく。

最終的なコードは以下のようになる。

2.x=π/2として,第二項までコーディングする

コーディングをする上で小さな値から始めることや具体的な値で試行錯誤することは重要だと思う。(個人の見解)。この記事でもその理念に則りx=π/2x=\pi/2として第二項まで,つまり

sinx=xx33! sinx=x-\frac{x^3}{3!}

までコーディングする。

import Foundation
var sum = 0.0  //int型とdouble型は足算できないので,0.0と書きdouble型にする。
var x = Double.pi/2

sum += x
sum += -(x*x*x)/Double(3*2*1)

sumxxを加え,次の行でx33!-\frac{x^3}{3!}を加えている。

最後に真値と比較するprint文を加える。

import Foundation
var sum = 0.0  //int型とdouble型は足算できないので,0.0と書きdouble型にする。
var x = Double.pi/2

sum += x
sum += -(x*x*x)/Double(3*2*1)

print(sum)//近似値0.9248322292886504
print(sin(Double.pi/2))//真値1.0

Double(3*2*1)としているのはInt型をDoule型に変換しているのだが,この記事では本質的な部分ではないので説明は割愛。

3.一般化しやすいように工夫する

さっきは第二項を-(x*x*x)/3*2*1としたが,これでは項数が増えるたびにxxを増やさなければならない。項数が増えても短くコーディングすることができるように工夫を加える。

import Foundation
var sum = 0.0  //int型とdouble型は足算できないので,0.0と書きdouble型にする。
var x = Double.pi/2

sum += x

for i in 2 ..< 3{
    x *= -(x*x)/Double((2*(i-1))*(2*i-1))
    sum += x
    print(x)
}

print(sum)//近似値0.9248322292886504
print(sin(Double.pi/2))//真値1.0

forを使い,項と変数iを対応させた。(1回しか実行されないが。)この場合第二項のみしか行わないので,for i in 2 ..< 3としている。一般化しているが,計算としては同じであるので2で出した答えと同じになるはずだ。

4.項数を増やす

一般化することによって項数を増やしても対応できる。

import Foundation
var sum = 0.0  //int型とdouble型は足算できないので,0.0と書きdouble型にする。
let x = Double.pi/2
var item = x

sum += item

for i in 2 ..< 6{
    item *= -(x*x)/Double((2*(i-1))*(2*i-1))
    sum += item
}

print(sum)//近似値1.00000035425842861
print(sin(Double.pi/2))//真値1.0

第6項までの近似,つまり

sinx=xx33!+x55!x77!+x99!x1111! sinx= x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\frac{x^9}{9!}-\frac{x^{11}}{11!}

ではほとんど誤差が無いことがわかる。