polar_to_cartesian.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // polartocartesian.go
  2. package main
  3. import (
  4. "bufio"
  5. "fmt"
  6. "math"
  7. "os"
  8. "runtime"
  9. "strconv"
  10. "strings"
  11. )
  12. type polar struct {
  13. radius float64
  14. Θ float64
  15. }
  16. type cartesian struct {
  17. x float64
  18. y float64
  19. }
  20. const result = "Polar: radius=%.02f angle=%.02f degrees -- Cartesian: x=%.02f y=%.02f\n"
  21. var prompt = "Enter a radius and an angle (in degrees), e.g., 12.5 90, " + "or %s to quit."
  22. func init() {
  23. if runtime.GOOS == "windows" {
  24. prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")
  25. } else { // Unix-like
  26. prompt = fmt.Sprintf(prompt, "Ctrl+D")
  27. }
  28. }
  29. func main() {
  30. questions := make(chan polar)
  31. defer close(questions)
  32. answers := createSolver(questions)
  33. defer close(answers)
  34. interact(questions, answers)
  35. }
  36. func createSolver(questions chan polar) chan cartesian {
  37. answers := make(chan cartesian)
  38. go func() {
  39. for {
  40. polarCoord := <-questions
  41. Θ := polarCoord.Θ * math.Pi / 180.0 // degrees to radians
  42. x := polarCoord.radius * math.Cos(Θ)
  43. y := polarCoord.radius * math.Sin(Θ)
  44. answers <- cartesian{x, y}
  45. }
  46. }()
  47. return answers
  48. }
  49. func interact(questions chan polar, answers chan cartesian) {
  50. reader := bufio.NewReader(os.Stdin)
  51. fmt.Println(prompt)
  52. for {
  53. fmt.Printf("Radius and angle: ")
  54. line, err := reader.ReadString('\n')
  55. if err != nil {
  56. break
  57. }
  58. line = line[:len(line)-1] // chop of newline character
  59. if numbers := strings.Fields(line); len(numbers) == 2 {
  60. polars, err := floatsForStrings(numbers)
  61. if err != nil {
  62. fmt.Fprintln(os.Stderr, "invalid number")
  63. continue
  64. }
  65. questions <- polar{polars[0], polars[1]}
  66. coord := <-answers
  67. fmt.Printf(result, polars[0], polars[1], coord.x, coord.y)
  68. } else {
  69. fmt.Fprintln(os.Stderr, "invalid input")
  70. }
  71. }
  72. fmt.Println()
  73. }
  74. func floatsForStrings(numbers []string) ([]float64, error) {
  75. var floats []float64
  76. for _, number := range numbers {
  77. if x, err := strconv.ParseFloat(number, 64); err != nil {
  78. return nil, err
  79. } else {
  80. floats = append(floats, x)
  81. }
  82. }
  83. return floats, nil
  84. }
  85. /* Output:
  86. Enter a radius and an angle (in degrees), e.g., 12.5 90, or Ctrl+Z, Enter to qui
  87. t.
  88. Radius and angle: 12.5 90
  89. Polar: radius=12.50 angle=90.00 degrees -- Cartesian: x=0.00 y=12.50
  90. Radius and angle: ^Z
  91. */