formatting.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. )
  7. func number(isBinary bool, v float64) string {
  8. if isBinary {
  9. return binary(v)
  10. } else {
  11. return metric(v)
  12. }
  13. }
  14. type prefix struct {
  15. Prefix string
  16. Multiplier float64
  17. }
  18. var metricPrefixes = []prefix{
  19. {"G", 1e9},
  20. {"M", 1e6},
  21. {"k", 1e3},
  22. }
  23. var binaryPrefixes = []prefix{
  24. {"Gi", 1 << 30},
  25. {"Mi", 1 << 20},
  26. {"Ki", 1 << 10},
  27. }
  28. func metric(v float64) string {
  29. return withPrefix(v, metricPrefixes)
  30. }
  31. func binary(v float64) string {
  32. return withPrefix(v, binaryPrefixes)
  33. }
  34. func withPrefix(v float64, ps []prefix) string {
  35. for _, p := range ps {
  36. if v >= p.Multiplier {
  37. return fmt.Sprintf("%.1f %s", v/p.Multiplier, p.Prefix)
  38. }
  39. }
  40. return fmt.Sprint(v)
  41. }
  42. // commatize returns a number with sep as thousands separators. Handles
  43. // integers and plain floats.
  44. func commatize(sep, s string) string {
  45. var b bytes.Buffer
  46. fs := strings.SplitN(s, ".", 2)
  47. l := len(fs[0])
  48. for i := range fs[0] {
  49. b.Write([]byte{s[i]})
  50. if i < l-1 && (l-i)%3 == 1 {
  51. b.WriteString(sep)
  52. }
  53. }
  54. if len(fs) > 1 && len(fs[1]) > 0 {
  55. b.WriteString(".")
  56. b.WriteString(fs[1])
  57. }
  58. return b.String()
  59. }