Calculating Pi with great accuracy

In this section, you will learn how to calculate Pi with great accuracy using a standard Go package named math/big and the special purpose types offered by that package.

This section contains the ugliest Go code that I have even seen! Even Java code looks better than this.

The name of the program that uses Bellard's formula to calculate Pi is calculatePi.go, and it will be presented in four parts.

The first part of calculatePi.go follows next:

package main 
 
import ( 
    "fmt" 
    "math" 
    "math/big" 
    "os" 
    "strconv" 
) 
 
var precision uint = 0 

The precision variable holds the desired precision of the calculations, and it is made global in order to be accessible from everywhere in the program.

The second code segment of calculatePi.go is shown in the following Go code:

func Pi(accuracy uint) *big.Float { 
    k := 0 
    pi := new(big.Float).SetPrec(precision).SetFloat64(0) 
    k1k2k3 := new(big.Float).SetPrec(precision).SetFloat64(0) 
    k4k5k6 := new(big.Float).SetPrec(precision).SetFloat64(0) 
    temp := new(big.Float).SetPrec(precision).SetFloat64(0) 
    minusOne := new(big.Float).SetPrec(precision).SetFloat64(-1) 
    total := new(big.Float).SetPrec(precision).SetFloat64(0) 
 
    two2Six := math.Pow(2, 6) 
    two2SixBig := new(big.Float).SetPrec(precision).SetFloat64(two2Six) 

The new(big.Float) call creates a new big.Float variable with the desired precision, which is set by SetPrec().

The third part of calculatePi.go contains the remaining Go code of the Pi() function:

    for { 
        if k > int(accuracy) { 
            break 
        } 
        t1 := float64(float64(1) / float64(10*k+9)) 
        k1 := new(big.Float).SetPrec(precision).SetFloat64(t1) 
        t2 := float64(float64(64) / float64(10*k+3)) 
        k2 := new(big.Float).SetPrec(precision).SetFloat64(t2) 
        t3 := float64(float64(32) / float64(4*k+1)) 
        k3 := new(big.Float).SetPrec(precision).SetFloat64(t3) 
        k1k2k3.Sub(k1, k2) 
        k1k2k3.Sub(k1k2k3, k3) 
        t4 := float64(float64(4) / float64(10*k+5)) 
        k4 := new(big.Float).SetPrec(precision).SetFloat64(t4) 
        t5 := float64(float64(4) / float64(10*k+7)) 
        k5 := new(big.Float).SetPrec(precision).SetFloat64(t5) 
        t6 := float64(float64(1) / float64(4*k+3)) 
        k6 := new(big.Float).SetPrec(precision).SetFloat64(t6) 
        k4k5k6.Add(k4, k5) 
        k4k5k6.Add(k4k5k6, k6) 
        k4k5k6 = k4k5k6.Mul(k4k5k6, minusOne) 
        temp.Add(k1k2k3, k4k5k6) 
 
        k7temp := new(big.Int).Exp(big.NewInt(-1), big.NewInt(int64(k)), nil) 
        k8temp := new(big.Int).Exp(big.NewInt(1024), big.NewInt(int64(k)), nil) 
        k7 := new(big.Float).SetPrec(precision).SetFloat64(0) 
        k7.SetInt(k7temp) 
        k8 := new(big.Float).SetPrec(precision).SetFloat64(0) 
        k8.SetInt(k8temp) 
 
        t9 := float64(256) / float64(10*k+1) 
        k9 := new(big.Float).SetPrec(precision).SetFloat64(t9) 
        k9.Add(k9, temp) 
        total.Mul(k9, k7) 
        total.Quo(total, k8) 
        pi.Add(pi, total) 
 
        k = k + 1 
    }
    pi.Quo(pi, two2SixBig) 
    return pi 
} 

This part of the program is the Go implementation of Bellard's formula. The bad thing about math/big is that you need a special function of it for almost every type of calculation. This is the case primarily because those functions keep the precision at the desired level. Thus, without using big.Float and big.Int variables, as well as the functions of math/big all of the time, you cannot compute Pi with the desired precision.

The last part of calculatePi.go shows the implementation of the main() function:

func main() { 
    arguments := os.Args 
    if len(arguments) == 1 { 
        fmt.Println("Please provide one numeric argument!") 
        os.Exit(1) 
    } 
 
    temp, _ := strconv.ParseUint(arguments[1], 10, 32) 
    precision = uint(temp) * 3 
 
    PI := Pi(precision) 
    fmt.Println(PI) 
} 

Executing calculatePi.go will generate the following type of output:

$ go run calculatePi.go
Please provide one numeric argument!
exit status 1
$ go run calculatePi.go 20
3.141592653589793258
$ go run calculatePi.go 200
3.141592653589793256960399361738762404019183156248573243493179283571046450248913467118511784317615354282017929416292809050813937875283435610586313363548602436768047706489838924381929

The moral of this section is that there are many different data types, and that you should use the right data type each time!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.4.181