リブートキャンプ by Swift 目次

 

 前回の説明を読めば「iPhoneアプリ開発、号外 IBMのSwiftサイト」のサンプルとして書いた、階乗計算のプログラムもわかるんじゃないかと思われ。

 

 1! 2! 3! 4! 5! ・・・

 

 ↓ループを使った階乗計算例

 

http://swift.sandbox.bluemix.net/#/repl/59479547ea3ae2065baec60f

 

 問題はその後の、マクローリン展開を使ったsin値の計算プログラムですな。
 ↓そもそもsin値ってなんだ?の中学生や、ダメダメの高2以上な人はここを見ましょう。
 

http://eleking.net/math/m-trigonometric/mt-trigonometric.html

 

 ↓最初、wikiを見ましょうと書こうと思ったけど…

 

https://ja.wikipedia.org/wiki/三角関数

 

 ムズイわっ!

 まあ、そんなわけでsin値です。こいつはマクローリン展開で以下のようなxの累乗と、階乗を使った計算の和で計算できるんですよ。


 ↓sin値のマクローリン展開(テイラー展開の一種)については、このページがわかりやすいような…

 ただ三角関数の微分についてなんかは説明してないので、知らないと読んでで目が点になるかも

 

http://www.yamamo10.jp/yamamoto/lecture/2006/3E/2nd/html/node2.html


 といっても、私もテイラー展開は、なんとなくそうなんだ〜て思うレベルですが、とにかくsin値は上の式で求まるらしい。

 けど、実際のとこどうなんだよっと、確かめたいけど、こんな式計算するのめんどくせーよっ、ということでプログラムで実践しますた。それがこの前のプログラム。

 

 ↓マクローリン展開を使ったsin値の計算例(上で作った累乗、階乗関数を利用)

 

http://swift.sandbox.bluemix.net/#/repl/59479a3eea3ae2065baec614

 

 結果、合ってる…

 すげーよ、テイラー、あんたすげーよ。

 power、factorial関数はそれぞれ、ループを使った累乗計算例、階乗計算例で作った関数をコピペして使ってます。

 

http://swift.sandbox.bluemix.net/#/repl/594793c6ea3ae2065baec60d

http://swift.sandbox.bluemix.net/#/repl/59479547ea3ae2065baec60f

 

 ちなみにループ使って、0度から90度までのsin値を求めてるんですが、テイラー展開でsinの引数xとして指定する角度の単位は1周を360分割する度数法ではなく、弧度法のラジアンが前提です。

 

 ↓ラジアン

 

https://ja.wikipedia.org/wiki/ラジアン

 

 なので、度数法単位から弧度法単位に変換する関数も作ってます。

//	angleで指定される360度単位の角度をラジアン単位に変換
func rad(angle:Double) ->Double {
	return 2.0 * 3.14 * (angle / 360.0)
}
 ここでretrunの横の演算式内で使ってる / (スラッシュ)は割り算の記号です。*(アスタリスク)は、前回の*=の説明で想像つくと思うけど掛け算の記号。 
 なので算数だと
 
    2 x 3.14 x (angle ÷ 360)
 
と書いてるのと同じことになります。この計算結果がrad関数の戻り値となる。
 後は、以下のif文を説明すれば、主役のsin関数の方も何やってるか理解できるでしょう。
        if (k % 2) == 1 {    // kが奇数の時だけ計算
            let factorial_k = factorial(x:k)         //  k!
            let power_x = power(base:x, exponent:k)  //  xのk乗
            result += Double(sign) * power_x / factorial_k
            sign *= -1       // 符号反転
        }
 ということで、まずは「k % 2」の%から。
 これはkを2で割った時の余りを計算するための記号です。
 例えばkの値が2なら、2で割った時の余りは0となり、3なら1、4なら0、5なら1となります。
 で、この計算結果を1と比較しているのが「== 1」の部分。
 これは == が値の一致を調べる記号で、 == の右辺と左辺が一致するときは真(正しい)、一致しないときは偽(正しくない)という結果を算出します。
 
 
 
 そして、この結果に合わせて動作を変えるのがif文です。ifキーワードの後ろが真の時だけ { } で囲まれた処理が実行されます。
 
 
 
 なので、kが1、3、5の時だけ
            let factorial_k = factorial(x:k)         //  k!
            let power_x = power(base:x, exponent:k)  //  xのk乗
            result += Double(sign) * power_x / factorial_k
            sign *= -1       // 符号反転
という処理が実行されることになります。
 これで、sin値のマクローリン展開の式が5!のレベルまで計算されることになるわけですよ。
 
 処理内で出てくるletというキーワードは定数宣言です。定数は変数と同じ記憶容器ですが、一度値を記憶したら後から変更できないようになってます。
    let factorial_k = factorial(x:k)
 と書くことで、factorial_kはfactorial(x:k)の戻り値で固定される。試しに
      let factorial_k = factorial(x:k)
      factorial_k = 0.0
とか書き込んでみるといいでしょう。Runさせると「無理!」って注意されます。
 
 ↓こんな感じで注意される
 
 
 { } の中で宣言された変数や定数は { } 内が寿命となっているので、ループ中のkが1、2、3、…と変化する処理ごとにfactorial_kは新しく作られ、factorial(x:k)の値が設定されます。
 それと
    result += Double(sign) * power_x / factorial_k
のDouble(sign)というのは、変数signがInt型なので、これをDouble型に変換しています。こうしないとDouble型のresult、power_xやfactorial_kとの演算式に組み込めません。
 ちなみにInt型に変換するときはInt(power_x)という風に書きます。
 型を統一するだけなら、Int型に合わす手もありますが、sin値をInt型で計算するの意味ないから。
 
 ループ使ってマクローリンを展開してるので
    for k in 1...15 {
なんかにすると、かなり精度が上がります。
 比較してるのは、swiftに用意された標準のsin関数の値。この標準のsin関数を呼び出すためにプログラム先頭で
import Foundation
てしてます。
 
 ↓Appleが公開してるC言語のsinのソースはここ(多分、今ならGitHubにも置かれてんじゃないかと思われ)
 
 ±π/4までは、13!までのマクローリン展開を使うっぽい。
 それ以上の大きさは、象限を分けてcosにしたりとか、色々調整するみたい。
 __ieee754_rem_pio2てのは渡された角度をπ/2で割った余りや象限を返す関数みたっす。
 
 ↓__kernel_sinソースの一部を移植
 
 結局、どっちもマクローリンかーいと突っ込んだところで、今回はおしまい。
 
 ということで、最後に指数関数と三角関数のテイラー展開から導き出されるオイラーの公式をたたえて、皆さん、ご一緒に〜
 
 
thumb
 
 でわでわ。
 
AD