Benchmarks
Monte Carlo
 previous   up   next 

The area under the curve y = sin(x2) and above the x-axis for x values between 0 and √π should be determined. This should be done with a Monte Carlo integration. The program should check 10000000 random points inside a rectangle where x is in the range [0, 2) and y is in the range [0. 1). A random point (x, y) is inside the region if y < sin(x2) holds.

C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>

int main(int argc, char *argv[]) {
  struct timeval time;

  gettimeofday(&time,NULL);
  srand48((unsigned int) time.tv_usec);

  int i, N = 10000000, num = 0;
  double x, y;

  for (i = 0; i < N; i++) {
    x = 2 * drand48();
    y = drand48();
    if (y < sin(x*x)) num++;
  }

  printf("%f\n", 2.0 * num / N);
  return 0;
}

Measurement:

prompt> gcc -lm -O2 sinx2area.c -o sinx2area
prompt> time ./sinx2area
0.894774

real    0m0.431s
user    0m0.431s
sys     0m0.000s

C++

#include <cstdio>
#include <cstdint>
#include <random>
#include <chrono>

using namespace std;
using randgen_t = minstd_rand;
using int32 = int_fast32_t;

static constexpr const int32 N = 10'000'000;

int main (int argc, char *argv[]) {
	minstd_rand::result_type default_seed =
		std::chrono::system_clock::now().time_since_epoch().count();
	randgen_t rand_gen{default_seed};

	int32 n = 0;
	for (int32 i = 0; i < N; ++i) {
		double x = (2.0 * rand_gen()) / randgen_t::max();
		double y = (1.0 * rand_gen()) / randgen_t::max();
		if (y < sin(x*x)) {
			n++;
		}
	}
	
	printf("%f\n", (2.0 * n) / N);
}

Measurement:

prompt> g++ -O3 -flto sinx2area.cpp -lm -o sinx2area
prompt> time ./sinx2area
0.894844

real    0m0.290s
user    0m0.286s
sys     0m0.004s

Go

package main

import (
   "fmt"
   "math"
   "math/rand"
   "time"
)

const N = 10000000
var x, y float64
var num int = 0

func main() {
   rand.Seed(time.Now().UnixNano())
   for i := 0; i < N; i++ {
      x := 2.0*rand.Float64()
      y := rand.Float64()
      if y < math.Sin(x*x) {
         num++
      }
   }
   fmt.Printf("%.7f\n", 2.0*float64(num)/float64(N))
}

Measurement:

prompt> go build sinx2area.go
prompt> time ./sinx2area
0.8946618

real    0m0.608s
user    0m0.601s
sys     0m0.008s

Java

public class sinx2area {
   public static void main (String[] args) {
      int N = 10000000;
      int num = 0;
      for (int i = 0; i < N; i++) {
         double x = 2.0 * Math.random();
         double y = Math.random();
         if (y < Math.sin(x*x)) num += 1;
      }
      System.out.println(2.0 * num / N);
    }
}

Measurement:

prompt> time java sinx2area
0.8944406

real    0m0.526s
user    0m0.539s
sys     0m0.016s

JavaScript

(function(){
	var N = 10000000;
	var num = 0;
	for (var i = 0; i < N; i ++) {
		var x = 2 * Math.random();
		var y = Math.random();
		if (y < Math.sin(x * x))
			num++;
	}
	console.log(2 * num / N);
})();

Measurement:

prompt> time node sinx2area.js
0.8952678

real    0m0.475s
user    0m0.453s
sys     0m0.024s

Perl

#!/usr/bin/perl

$n=10000000;
$tot=0;

for($i=1;$i<=$n;$i++){
    $x=2*rand();
    $y=rand();
    
    if($y<sin($x*$x)){
        $tot++;
    }
}
$area=(2.0*$tot)/$n;
print "$area\n";

Measurement:

prompt> time perl sinx2area.pl
0.8940136

real    0m3.046s
user    0m3.038s
sys     0m0.000s

Python 2

#!/usr/bin/python
import random
import math

max=10000000
tot=0

for i in range(1,max+1):
    x=2*random.random()
    y=random.random()
    if y < math.sin(x*x):
        tot=tot+1

area=(2.0*tot/max)
print "%0.5f" %(area)

Measurement:

prompt> time python sinx2area.py 
0.89431

real    0m4.480s
user    0m4.402s
sys     0m0.076s

Ruby

#!/usr/bin/ruby

N = 10000000
num = 0
for i in 1 .. N do
    x = 2 * rand()
    y = rand()
    num += 1 if (y < Math.sin(x**2))
end
area = (2.0 * num) / N
puts(area)

Measurement:

prompt> time ruby sinx2area.rb
0.8949598

real    0m2.960s
user    0m2.947s
sys     0m0.013s

Seed7

$ include "seed7_05.s7i";
  include "float.s7i";
  include "math.s7i";

const proc: main is func
  local
    const integer: N is 10000000;
    var integer: num is 0;
    var float: x is 0.0;
    var float: y is 0.0;
  begin
    for N do
      x := rand(0.0, 2.0);
      y := rand(0.0, 1.0);
      num +:= ord(y < sin(x*x));
    end for;
    writeln(2.0 * flt(num) / flt(N) digits 7);
  end func;

Measurement:

prompt> s7c -O2 -oc3 sinx2area
prompt> time ./sinx2area
0.8947734

real    0m0.223s
user    0m0.223s
sys     0m0.000s

 previous   up   next