Skip to content

Instantly share code, notes, and snippets.

@CodeZombie
Last active March 30, 2016 00:33
Show Gist options
  • Save CodeZombie/ef15d4d1b4ade2868e2b to your computer and use it in GitHub Desktop.
Save CodeZombie/ef15d4d1b4ade2868e2b to your computer and use it in GitHub Desktop.
Pi Estimator using Montecarlo method in Go
/*
/ ########
/ # ## #
/ # # # #
/ ## ##
/ # #
/ # #
/ ## ##
/ # # # #
/ # ## #
/ ########
/
/ This is an implementation of the Montecarlo method used to estimate Pi to 16 digits
/ It works by randomly choosing a point in a 1x1 square to 64bit floating point accuracy
/ This point is then checked to see if it is within a perfectly contained circle within this square using the formula: x^2 + y^2 < radius^2
/ The number of points placed, and the number of points inside the circle are tracked
/ Pi is estimated by the following formua: (4 * <number of points in the circle>) / <number of points>
*/
package main
import (
"fmt"
"os"
"os/exec"
"math"
"math/rand"
"time"
)
func clearConsole() { //windows-only console-clear
cmd := exec.Command("cmd", "/c", "cls")
cmd.Stdout = os.Stdout
cmd.Run()
return
}
func printScreen(trials_ int, estPi_ float64, startTime_ time.Time) {
clearConsole()
elapsedTime := time.Since(startTime_)
fmt.Println("--------Montecarlo Pi Estimator--------")
fmt.Println("| Running... |")
fmt.Println("| |")
fmt.Printf( "| Trials: %-18d |\n", trials_) //pad and left-justify the number
fmt.Printf( "| Est of Pi: ~%-18g |\n", estPi_)
fmt.Println("| Actual Pi: 3.1415926535897932 |")
fmt.Printf( "| Run Time: %#18s |\n", fmt.Sprintf("%01d days %02d:%02d:%02d", uint32(elapsedTime.Hours())/24,
uint32(elapsedTime.Hours()) % 24,
uint32(elapsedTime.Minutes()) % 60,
uint32(elapsedTime.Seconds()) % 60))
fmt.Println("---------------------------------------")
}
func main() {
totalCount, insideCount := 0, 0
rand.Seed(time.Now().UTC().UnixNano()) //seed with a timestamp
startTime := time.Now()
printScreen(0, 0, startTime)
for true {
// checks to see if a randomly generated point is within a circle with a radius of 1 unit
// the formula for this is x^2 + y^2 < r^2, where x and y are random floats between 0 and 1, and r is 1 (1^2 == 1)
if math.Pow(rand.Float64(), 2) + math.Pow(rand.Float64(), 2) < 1 {
insideCount++
}
totalCount++
if totalCount % 10000000 == 0{ //only show output every ten million calculations. (becuase fmt.Print* is slow)
printScreen(totalCount, float64(4*insideCount)/float64(totalCount), startTime)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment