diff --git a/30-concurrency/xxx-monte-carlo/main.go b/30-concurrency/xxx-monte-carlo/main.go new file mode 100644 index 0000000..99fe59f --- /dev/null +++ b/30-concurrency/xxx-monte-carlo/main.go @@ -0,0 +1,80 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +import ( + "fmt" + "math" + "math/rand" + "os" + "runtime" + "strconv" + "time" +) + +func main() { + if len(os.Args) != 2 { + exit("Please provide the sample rate") + } + + samples, err := strconv.Atoi(os.Args[1]) + if err != nil { + exit("Incorrect sample rate") + } + + elapse := measure(time.Now()) + pi := spread(samples, runtime.NumCPU()) + + fmt.Println("PI : ", pi) + fmt.Println("Time: ", elapse()) +} + +func exit(msg string) { + fmt.Fprintln(os.Stderr, msg) + os.Exit(1) +} + +func measure(start time.Time) func() time.Duration { + return func() time.Duration { + return time.Since(start) + } +} + +// spread the work to P number of estimate go funcs. +// returns the estimation. +func spread(samples int, P int) (estimated float64) { + counts := make(chan float64) + + for i := 0; i < P; i++ { + go func() { counts <- estimate(samples / P) }() + } + + for i := 0; i < P; i++ { + estimated += <-counts + } + return estimated / float64(P) +} + +func estimate(N int) float64 { + const radius = 1.0 + + var ( + seed = rand.NewSource(time.Now().UnixNano()) + random = rand.New(seed) + inside int + ) + + for i := 0; i < N; i++ { + x, y := random.Float64(), random.Float64() + + if num := math.Sqrt(x*x + y*y); num < radius { + inside++ + } + } + return 4 * float64(inside) / float64(N) +}