本日は
c2nim で c で書いたコードをNimに変換してみようという話です.
相変わらずモンテカルロ法ですね...
変換対象
cmonte.c
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
//http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html#Uniform
double UniformRandom01(void){
return ((double)rand()+1.0)/((double)RAND_MAX+2.0);
}
int main(void){
srand(time(NULL));
const int N=100000000;
int counter=0;
for (int i=0;i<N;++i){
double x=UniformRandom01();
double y=UniformRandom01();
if (x*x+y*y<1.0){
counter+=1;
}
}
printf("approx pi is %f\n", 4*counter/(double)N);
}
相変わらずの円周率を求めるプログラムです.
c2nim で変換
変換してみましょう.ここではWindows10でおこないました.
> c2nim cmonte.c
なんとこれだけで行けます.もしやこれだけでNimは動かせるのだろうか...
cmonte.nim
## http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html#Uniform
proc UniformRandom01*(): cdouble =
return (cast[cdouble](rand()) + 1.0) div (cast[cdouble](RAND_MAX) + 2.0)
proc main*(): cint =
srand(time(nil))
var N: cint = 100000000
var counter: cint = 0
var i: cint = 0
while i < N:
var x: cdouble = UniformRandom01()
var y: cdouble = UniformRandom01()
if x * x + y * y < 1.0:
inc(counter, 1)
inc(i)
printf("approx pi is %f\x0A", 4 * counter div cast[cdouble](N))
と思ったんですけれど結構形式的な置き換えのようですね.そして読める!読めるぞ! include の対象は考慮しないみたい.少し考えればそりゃそうだとなりますが.まず,ランダムモジュールの部分を直さなければいけませんね.
手動修正後
modefied.nim
import random
randomize()
proc UniformRandom01*(): float =
return random(max=1.0)
proc main*(): int =
var N: int = 100000000
var counter: int = 0
var i: int = 0
while i < N:
var x: float = UniformRandom01()
var y: float = UniformRandom01()
if x * x + y * y < 1.0:
inc(counter, 1)
inc(i)
echo "approx pi is \x0A", 4.0 * counter.float / N.float
when isMainModule:
discard main()
こんな感じになります.最初から手書きで移植するよりかは骨組みを作ってくれる分ましかもという感じで使えればいいのかな.
CからNimへの変換前後のコードで厳密なパフォーマンスは測定していませんが,体感ほぼ変わらない感じです.