statistics.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // statistics.go
  2. package main
  3. import (
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. )
  11. type statistics struct {
  12. numbers []float64
  13. mean float64
  14. median float64
  15. }
  16. const form = `<html><body><form action="/" method="POST">
  17. <label for="numbers">Numbers (comma or space-separated):</label><br>
  18. <input type="text" name="numbers" size="30"><br />
  19. <input type="submit" value="Calculate">
  20. </form></html></body>`
  21. const error = `<p class="error">%s</p>`
  22. var pageTop = ""
  23. var pageBottom = ""
  24. func main() {
  25. http.HandleFunc("/", homePage)
  26. if err := http.ListenAndServe(":9001", nil); err != nil {
  27. log.Fatal("failed to start server", err)
  28. }
  29. }
  30. func homePage(writer http.ResponseWriter, request *http.Request) {
  31. writer.Header().Set("Content-Type", "text/html")
  32. err := request.ParseForm() // Must be called before writing response
  33. fmt.Fprint(writer, pageTop, form)
  34. if err != nil {
  35. fmt.Fprintf(writer, error, err)
  36. } else {
  37. if numbers, message, ok := processRequest(request); ok {
  38. stats := getStats(numbers)
  39. fmt.Fprint(writer, formatStats(stats))
  40. } else if message != "" {
  41. fmt.Fprintf(writer, error, message)
  42. }
  43. }
  44. fmt.Fprint(writer, pageBottom)
  45. }
  46. func processRequest(request *http.Request) ([]float64, string, bool) {
  47. var numbers []float64
  48. var text string
  49. if slice, found := request.Form["numbers"]; found && len(slice) > 0 {
  50. //处理如果网页中输入的是中文逗号
  51. if strings.Contains(slice[0], "&#65292") {
  52. text = strings.Replace(slice[0], "&#65292;", " ", -1)
  53. } else {
  54. text = strings.Replace(slice[0], ",", " ", -1)
  55. }
  56. for _, field := range strings.Fields(text) {
  57. if x, err := strconv.ParseFloat(field, 64); err != nil {
  58. return numbers, "'" + field + "' is invalid", false
  59. } else {
  60. numbers = append(numbers, x)
  61. }
  62. }
  63. }
  64. if len(numbers) == 0 {
  65. return numbers, "", false // no data first time form is shown
  66. }
  67. return numbers, "", true
  68. }
  69. func getStats(numbers []float64) (stats statistics) {
  70. stats.numbers = numbers
  71. sort.Float64s(stats.numbers)
  72. stats.mean = sum(numbers) / float64(len(numbers))
  73. stats.median = median(numbers)
  74. return
  75. }
  76. func sum(numbers []float64) (total float64) {
  77. for _, x := range numbers {
  78. total += x
  79. }
  80. return
  81. }
  82. func median(numbers []float64) float64 {
  83. middle := len(numbers) / 2
  84. result := numbers[middle]
  85. if len(numbers)%2 == 0 {
  86. result = (result + numbers[middle-1]) / 2
  87. }
  88. return result
  89. }
  90. func formatStats(stats statistics) string {
  91. return fmt.Sprintf(`<table border="1">
  92. <tr><th colspan="2">Results</th></tr>
  93. <tr><td>Numbers</td><td>%v</td></tr>
  94. <tr><td>Count</td><td>%d</td></tr>
  95. <tr><td>Mean</td><td>%f</td></tr>
  96. <tr><td>Median</td><td>%f</td></tr>
  97. </table>`, stats.numbers, len(stats.numbers), stats.mean, stats.median)
  98. }