number.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package humanize
  2. import (
  3. "math"
  4. "strconv"
  5. )
  6. var (
  7. renderFloatPrecisionMultipliers = [...]float64{
  8. 1,
  9. 10,
  10. 100,
  11. 1000,
  12. 10000,
  13. 100000,
  14. 1000000,
  15. 10000000,
  16. 100000000,
  17. 1000000000,
  18. }
  19. renderFloatPrecisionRounders = [...]float64{
  20. 0.5,
  21. 0.05,
  22. 0.005,
  23. 0.0005,
  24. 0.00005,
  25. 0.000005,
  26. 0.0000005,
  27. 0.00000005,
  28. 0.000000005,
  29. 0.0000000005,
  30. }
  31. )
  32. // FormatFloat produces a formatted number as string based on the following user-specified criteria:
  33. // * thousands separator
  34. // * decimal separator
  35. // * decimal precision
  36. //
  37. // Usage: s := RenderFloat(format, n)
  38. // The format parameter tells how to render the number n.
  39. //
  40. // See examples: http://play.golang.org/p/LXc1Ddm1lJ
  41. //
  42. // Examples of format strings, given n = 12345.6789:
  43. // "#,###.##" => "12,345.67"
  44. // "#,###." => "12,345"
  45. // "#,###" => "12345,678"
  46. // "#\u202F###,##" => "12 345,68"
  47. // "#.###,###### => 12.345,678900
  48. // "" (aka default format) => 12,345.67
  49. //
  50. // The highest precision allowed is 9 digits after the decimal symbol.
  51. // There is also a version for integer number, FormatInteger(),
  52. // which is convenient for calls within template.
  53. func FormatFloat(format string, n float64) string {
  54. // Special cases:
  55. // NaN = "NaN"
  56. // +Inf = "+Infinity"
  57. // -Inf = "-Infinity"
  58. if math.IsNaN(n) {
  59. return "NaN"
  60. }
  61. if n > math.MaxFloat64 {
  62. return "Infinity"
  63. }
  64. if n < (0.0 - math.MaxFloat64) {
  65. return "-Infinity"
  66. }
  67. // default format
  68. precision := 2
  69. decimalStr := "."
  70. thousandStr := ","
  71. positiveStr := ""
  72. negativeStr := "-"
  73. if len(format) > 0 {
  74. format := []rune(format)
  75. // If there is an explicit format directive,
  76. // then default values are these:
  77. precision = 9
  78. thousandStr = ""
  79. // collect indices of meaningful formatting directives
  80. formatIndx := []int{}
  81. for i, char := range format {
  82. if char != '#' && char != '0' {
  83. formatIndx = append(formatIndx, i)
  84. }
  85. }
  86. if len(formatIndx) > 0 {
  87. // Directive at index 0:
  88. // Must be a '+'
  89. // Raise an error if not the case
  90. // index: 0123456789
  91. // +0.000,000
  92. // +000,000.0
  93. // +0000.00
  94. // +0000
  95. if formatIndx[0] == 0 {
  96. if format[formatIndx[0]] != '+' {
  97. panic("RenderFloat(): invalid positive sign directive")
  98. }
  99. positiveStr = "+"
  100. formatIndx = formatIndx[1:]
  101. }
  102. // Two directives:
  103. // First is thousands separator
  104. // Raise an error if not followed by 3-digit
  105. // 0123456789
  106. // 0.000,000
  107. // 000,000.00
  108. if len(formatIndx) == 2 {
  109. if (formatIndx[1] - formatIndx[0]) != 4 {
  110. panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers")
  111. }
  112. thousandStr = string(format[formatIndx[0]])
  113. formatIndx = formatIndx[1:]
  114. }
  115. // One directive:
  116. // Directive is decimal separator
  117. // The number of digit-specifier following the separator indicates wanted precision
  118. // 0123456789
  119. // 0.00
  120. // 000,0000
  121. if len(formatIndx) == 1 {
  122. decimalStr = string(format[formatIndx[0]])
  123. precision = len(format) - formatIndx[0] - 1
  124. }
  125. }
  126. }
  127. // generate sign part
  128. var signStr string
  129. if n >= 0.000000001 {
  130. signStr = positiveStr
  131. } else if n <= -0.000000001 {
  132. signStr = negativeStr
  133. n = -n
  134. } else {
  135. signStr = ""
  136. n = 0.0
  137. }
  138. // split number into integer and fractional parts
  139. intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision])
  140. // generate integer part string
  141. intStr := strconv.FormatInt(int64(intf), 10)
  142. // add thousand separator if required
  143. if len(thousandStr) > 0 {
  144. for i := len(intStr); i > 3; {
  145. i -= 3
  146. intStr = intStr[:i] + thousandStr + intStr[i:]
  147. }
  148. }
  149. // no fractional part, we can leave now
  150. if precision == 0 {
  151. return signStr + intStr
  152. }
  153. // generate fractional part
  154. fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision]))
  155. // may need padding
  156. if len(fracStr) < precision {
  157. fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr
  158. }
  159. return signStr + intStr + decimalStr + fracStr
  160. }
  161. // FormatInteger produces a formatted number as string.
  162. // See FormatFloat.
  163. func FormatInteger(format string, n int) string {
  164. return FormatFloat(format, float64(n))
  165. }