頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


すごく便利!ブロック構文を使って式を得る

アプリ内でたくさんの式を扱うとするよ。
yy = -34.9456869602161078*pow(xx,0)
+110.1711990130272056*pow(xx,1)
-42.2603582000001268*pow(xx,2)
+8.8934314905976777*pow(xx,3)
-1.0504024065048447*pow(xx,4)
+0.0697635676738542*pow(xx,5)
-0.0024233376396043*pow(xx,6)
+0.0000341459080453*pow(xx,7);
↑こんな感じのがたくさんあるんだ。
これは「赤ちゃんの成長グラフ」で使う近似式なんだけど、これをどういう風にアプリ内に持っておけばいいんだろう?って思ってさ。

最初はクラスメソッド(クラス名を'ApproxEquation'ってしとくよ)にしてこんな感じにしてたんだよ。
+(double)getYforX:(double)xx option1:(int)option1 option2:(int)option2 …
{
    double yy;
    if (option1 == 0) {
        if (option2 == 0) {
            switch(option3) {
                //略

    return yy;
} 
↑かなりざっくりだけど、いろんな条件で式を場合分けする必要があるんだよ。
条件としては性別や身長or体重とか、何歳から何歳までに使える式だとかまあそういうのがいくつもあるんだ。
呼び出し元でそういう条件全てとxxを指定してコールするんだけど、値をまとめて欲しい時があるんだよ。
近似式なので近似曲線を描こうとすると、表示する範囲内でxxを100分割して少しずつ大きくしていくxxに応じたyyを得る、とかまあそんなのね。よくあるでしょ。

これを実装しようと
for (int ii=0;ii < 100;ii++) {
    double xx = offsetX + ii*unitX;
    double yy = [ApproxEquation getYforX:xx option1:MALE option2:HEIGHT …
    //配列に入れていくとか
}
こんな感じに記述すると、毎回呼び出し先でいくつも条件判定をしてから計算されることになるよね。
条件判定を何回もするのってなんか無駄じゃない?

結構な計算量になるからなんとか高速化したいと思っていろいろ調べたらさ、ブロック構文で実現できるみたいなんだ。
要は式を取ってくるってこと。

するとさっきの呼び出し元は先に式を得てるからループ内で条件判定する必要がないことになるんだ。
{
    Approximation approximation = [ApproxEquation getEquationOption1:MALE option2:HEIGHT …
    for (int ii=0;ii < 100;ii++) {
        double xx = offsetX + ii*unitX;
        double yy = approximation(xx);
        //配列に入れていくとか
   }
}
↑ああ、なんかすっきりするよね!

Approximationってのは次のように定義されるブロック変数だ。
typedef double (^Approximation)(double xx);
↑'Approximation'って変数名でdouble xxをもらってdoubleの値を返すってことだよね。

式自体を定義して、条件に応じて必要な式を返すクラスメソッドはこんな感じになる。
+(Approximation) getEquationOption1:(int)option1 option2:(int)option2 …
{
    Approximation approximation;
     if (option1 == 0) {
        if (option2 == 0) {
            switch(option3) {
              //略
                approximation = ^(double xx) {
                    return -34.9456869602161078*pow(xx,0)
+110.1711990130272056*pow(xx,1)
-42.2603582000001268*pow(xx,2)
+8.8934314905976777*pow(xx,3)
-1.0504024065048447*pow(xx,4)
+0.0697635676738542*pow(xx,5)
-0.0024233376396043*pow(xx,6)
+0.0000341459080453*pow(xx,7);                    
                };

    //略

    return approximation;
}
↑こんな構成で式を返す。便利だねえ!

<< アメリカ横断ウルトラクイズのあの曲はRandy Newmanみたい   TopPage  Gingerがすごい!のか? >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/770-e4f3d2af




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad