路漫漫其修远兮
吾将上下而求索

go学习:计算pi和笛卡尔坐标,使用协程

1、计算pi

参考公式

14.4_piseries.png

package main

import (
   "fmt"
   "math"
   "time"
)

func main() {
   start := time.Now()
   fmt.Println(CalculatePi(5000))
   end := time.Now()
   delta := end.Sub(start)
   fmt.Printf("longCalculation took this amount of time: %s\n", delta)
}

// CalculatePi launches n goroutines to compute an
// series-approximation of pi.
func CalculatePi(n int) float64 {
   ch := make(chan float64)
   for k := 0; k <= n; k++ {
      // calculate k-th term in the series
      go term(ch, float64(k))
   }
   f := 0.0
   //wait for all goroutines to complete, get and sum up their results:
   for k := 0; k <= n; k++ {
      f += <-ch
   }
   return f
}

func term(ch chan float64, k float64) {
   ch <- 4 * math.Pow(-1, k) / (2*k + 1)
}

下面使用多线程

package main

import (
   "fmt"
   "math"
   "os"
   "runtime"
   "strconv"
   "time"
)

const LEN = 9e12

func main() {
   var NCPU int
   start := time.Now()

   if len(os.Args) == 1 {
      NCPU = 2
   } else {
      NCPU, _ = strconv.Atoi(os.Args[1])
   }
   fmt.Println("CPU ", NCPU)

   runtime.GOMAXPROCS(NCPU)
   fmt.Println(CalculatePi(LEN, NCPU))
   end := time.Now()
   delta := end.Sub(start)
   fmt.Printf("longCalculation took this amount of time: %s\n", delta)
}

func CalculatePi(end, NCPU int) float64 {
   ch := make(chan float64)
   for i := 0; i < NCPU; i++ {
      go term(ch, i*end/NCPU, (i+1)*end/NCPU)
   }
   result := 0.0
   for i := 0; i < NCPU; i++ {
      result += <-ch
   }

   return result
}

func term(ch chan float64, start, end int) {
   result := 0.0
   for i := start; i < end; i++ {
      x := float64(i)
      result += 4 * (math.Pow(-1, x) / (2.0*x + 1.0))
   }
   ch <- result
   fmt.Printf("%d - %d is done\n", start, end)
}

在服务器上使用12核心来进行运算,结果如下,可将π精确到小数点后12位

[root@master ~]#go run pi.go 12
CPU  12
0 - 750000000000 is done
750000000000 - 1500000000000 is done
1500000000000 - 2250000000000 is done
2250000000000 - 3000000000000 is done
3000000000000 - 3750000000000 is done
3750000000000 - 4500000000000 is done
4500000000000 - 5250000000000 is done
5250000000000 - 6000000000000 is done
6750000000000 - 7500000000000 is done
6000000000000 - 6750000000000 is done
7500000000000 - 8250000000000 is done
8250000000000 - 9000000000000 is done
3.141592653588403
longCalculation took this amount of time: 42h54m25.498164997s

2、写一个可交互的控制台程序,要求用户输入二位平面极坐标上的点(半径和角度(度))。计算对应的笛卡尔坐标系的点的 x 和 y 并输出。使用极坐标和笛卡尔坐标的结构体。

package main    
import (    
	"bufio"    
	"fmt"    
	"math"    
	"os"    
	"runtime"    
	"strconv"    
	"strings"    
)    
type polar struct {    
	radius float64    
	Θ      float64    
}    
type cartesian struct {    
	x float64    
	y float64    
}    
const result = "Polar: radius=%.02f angle=%.02f degrees -- Cartesian: x=%.02f y=%.02f\n"    
var prompt = "Enter a radius and an angle (in degrees), e.g., 12.5 90, " + "or %s to quit."    
func init() {    
	if runtime.GOOS == "windows" {    
		prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")    
	} else { // Unix-like    
		prompt = fmt.Sprintf(prompt, "Ctrl+D")    
	}    
}    
func main() {    
	questions := make(chan polar)    
	defer close(questions)    
	answers := createSolver(questions)    
	defer close(answers)    
	interact(questions, answers)    
}    
func createSolver(questions chan polar) chan cartesian {    
	answers := make(chan cartesian)    
	go func() {    
		for {    
			polarCoord := <-questions    
			Θ := polarCoord.Θ * math.Pi / 180.0 // degrees to radians    
			x := polarCoord.radius * math.Cos(Θ)    
			y := polarCoord.radius * math.Sin(Θ)    
			answers <- cartesian{x, y}    
		}    
	}()    
	return answers    
}    
func interact(questions chan polar, answers chan cartesian) {    
	reader := bufio.NewReader(os.Stdin)    
	fmt.Println(prompt)    
	for {    
		fmt.Printf("Radius and angle: ")    
		line, err := reader.ReadString('\n')    
		if err != nil {    
			break    
		}    
		line = line[:len(line)-1] // chop of newline character    
		if numbers := strings.Fields(line); len(numbers) == 2 {    
			polars, err := floatsForStrings(numbers)    
			if err != nil {    
				fmt.Fprintln(os.Stderr, "invalid number")    
				continue    
			}    
			questions <- polar{polars[0], polars[1]}    
			coord := <-answers    
			fmt.Printf(result, polars[0], polars[1], coord.x, coord.y)    
		} else {    
			fmt.Fprintln(os.Stderr, "invalid input")    
		}    
	}    
	fmt.Println()    
}    
func floatsForStrings(numbers []string) ([]float64, error) {    
	var floats []float64    
	for _, number := range numbers {    
		if x, err := strconv.ParseFloat(number, 64); err != nil {    
			return nil, err    
		} else {    
			floats = append(floats, x)    
		}    
	}    
	return floats, nil    
}

参考文档:https://github.com/andyblog/the-way-to-go_ZH_CN/blob/master/eBook/14.4.md

未经允许不得转载:江哥架构师笔记 » go学习:计算pi和笛卡尔坐标,使用协程

分享到:更多 ()

评论 抢沙发

评论前必须登录!