Quantcast
Channel: 円周率近似値の日に生まれて理系じゃないわけないだろ! - knifeのblog
Viewing all articles
Browse latest Browse all 5376

等角連続整数辺多角形は存在するのか? その2

$
0
0

昨日の続きです。

さて、プログラムの高速化という話しなのですが、あのプログラムのどこがボトルネックだったのでしょうか。

正解は、数学関連の関数、つまりmath.hで定義されている関数です。

階乗的に増え続けるパターン数、その再帰処理ループの中に時間の架かる計算をさせていては高速化は望めませんね。

例えば、レンジ内に収まっているのかをピタゴラスの定理で距離を求めていました。

z = sqrt(x*x+y*y);
if ( z < r ) {
    /* 出力処理 */
}

これね。
sqrt();関数は時間がかかるんですよ。
ならば、レンジのrを2乗したr2と、sqrt();せずにzの2乗したものを比較するほうが早い。

z2 = x*x+y*y;
if ( z2 < r2 ) {
    /* 出力処理 */
}

さて、もう一つ、いや二つ、数学関連関数を使っていますよね。
そうです、sin();、cos();です。

x = 0.0;
y = 0.0;
a = 360.0/m;
for (i=0; i<m; i++) {
    x += l[i]*cos(a*i*M_PI/180.0);
    y -= l[i]*cos(a*i*M_PI/180.0);
}


これこれ。
毎回、同じ値にl[i]を掛けているだけなんですよ。
ならば、事前に配列に格納しておいて、再帰処理ループ内では配列を使えばいいですね。

main()の中で、

a = b = 2.0*M_PI/180.0;
c[0] = 1.0;
s[0] = 0.0;
for (i=1; i<m; i++, b+=a) {
    c[i] = cos(b);
    s[i] = sin(b);
}

こんな感じで予め配列に値を格納しておいて、再帰処理内で、


x = 1.0;
y = 0.0;
for (i=1; i<m; i++) {
    x += l[i]*c[i];
    y -= l[i]*s[i];
}

とすれば、前のプログラムよりかなりの速度アップが望めました。

また、x, yの値も、上記のループをやらず、再帰処理でデータとして渡して、各々やれば、もう少し速くなるかもしれませんが、再帰処理にあんまりデータを渡すのは好きじゃないんだけど、まぁ速度アップが見込めるならばやってもいいかな。


さて、mがいくつのとき、解があって、解の個数がどれくらいだと予想されましたでしょうか?

 

mpatternloopsample
301 
403 
5012NEAR 1 4 3 2 5
62601 4 5 2 3 6
1 5 3 4 2 6
70360NEAR 1 4 7 2 3 5 6
802520NEAR 1 4 7 3 6 2 5 8
9020160NEAR 1 5 9 4 2 6 7 3 8
10241814401  8  2  9  5  6  3  7  4 10
1  8  4  7  5  6  3  9  2 10
1101814400NEAR 1  8  9  5  2  6 10  7  3  4 11
12732199584001  5 10  3  9 11  4  2  7  6 12  8
130239500800NEAR 1  2  7 12 13  4  5  3  8  6 11  9 10
1472031135104001 12  5  4  7 10 13  2 11  6  3  8  9 14
1548435891456001  9 14  4 12  2  7 15  5 10  3  8 13  6 11
16解析中653837184000 
17解析中11115232128000 
18検討中188958946176000 

 

私の予想はmが6の倍数ならば必ず解があるだろう。
mが偶数ならば、pがある程度あれば解があるだろう。
mが奇数ならば、偶数よりは難しいかもしれないが、解があったらいいな。
程度でした。

m=10、12、14で解があったこと、m=15で解があったことは、ある程度予想通りでした。
次の記事は、m=16の解析待ちですかね。
 

 

ではでは


Viewing all articles
Browse latest Browse all 5376

Trending Articles