iPhoneモンテカルロPI

モンテカルロ法っぽくPIを計算するiPhoneアプリ(C++)のサンプルコードを描いてみます。

#import “ViewController.h”

#include <memory>

#include <vector>

using namespace std;

std::vector<CGPoint> pts;

#define RADIUS 1

class MonteCarloPi {

public:

    CGPoint createRandomPoint();

    float mon_pi();

};

CGPoint MonteCarloPi::createRandomPoint() {

    // 0 ~ 1

    float x = rand() % 100;

    float y = rand() % 100;

    CGPoint p = CGPointMake(x / 100.0, y / 100.0);

    pts.push_back(p);

    return p;

}

float MonteCarloPi::mon_pi() {

    float validCount = 0;

    float count = pts.size();

    for (auto& p : pts) {

        if (p.x * p.x + p.y * p.y <= RADIUS)

            validCount += 1;

    }

    return 4.0 * validCount / count;

}

@interface ViewController ()

@property (nonatomic) std::shared_ptr<MonteCarloPi> _cppClass;

@property (nonatomic, weak) UILabel *label;

@end

@implementation ViewController {

    BOOL _start;

}

– (void)viewDidLoad {

    [super viewDidLoad];

    std::shared_ptr<MonteCarloPi> _cppClass(new MonteCarloPi());

    

    UILabel *l = [[UILabel alloc] init];

    l.text = [NSString stringWithFormat:@”%.2f”, 0.0];

    [l sizeToFit];

    l.center = CGPointMake(CGRectGetMidX(self.view.bounds), 300);

    [self.view addSubview:l];

    self.label = l;

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    if (_start == NO) {

        [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(createRandomPoint:) userInfo:nil repeats:YES];

    }

}

– (void)createRandomPoint:(NSTimer *)timer {

    CGPoint p = self._cppClass->createRandomPoint();

    CALayer *l = [CALayer layer];

    l.frame = CGRectMake(p.x * CGRectGetMaxX(self.view.bounds), p.y * CGRectGetMaxX(self.view.bounds), 2, 2);

    l.backgroundColor = (p.x * p.x + p.y * p.y <= 1)

        ? [UIColor blueColor].CGColor

        : [UIColor redColor].CGColor;

    [self.view.layer addSublayer:l];

    

    self.label.text = [NSString stringWithFormat:@”%f.2″, self._cppClass->mon_pi()];

    [self.label sizeToFit];

    

    if (pts.size() > 4000) {

        [timer invalidate];

        return;

    }

}

@end