cubefs

Форк
0
192 строки · 4.2 Кб
1
package humanize
2

3
/*
4
Slightly adapted from the source to fit go-humanize.
5

6
Author: https://github.com/gorhill
7
Source: https://gist.github.com/gorhill/5285193
8

9
*/
10

11
import (
12
	"math"
13
	"strconv"
14
)
15

16
var (
17
	renderFloatPrecisionMultipliers = [...]float64{
18
		1,
19
		10,
20
		100,
21
		1000,
22
		10000,
23
		100000,
24
		1000000,
25
		10000000,
26
		100000000,
27
		1000000000,
28
	}
29

30
	renderFloatPrecisionRounders = [...]float64{
31
		0.5,
32
		0.05,
33
		0.005,
34
		0.0005,
35
		0.00005,
36
		0.000005,
37
		0.0000005,
38
		0.00000005,
39
		0.000000005,
40
		0.0000000005,
41
	}
42
)
43

44
// FormatFloat produces a formatted number as string based on the following user-specified criteria:
45
// * thousands separator
46
// * decimal separator
47
// * decimal precision
48
//
49
// Usage: s := RenderFloat(format, n)
50
// The format parameter tells how to render the number n.
51
//
52
// See examples: http://play.golang.org/p/LXc1Ddm1lJ
53
//
54
// Examples of format strings, given n = 12345.6789:
55
// "#,###.##" => "12,345.67"
56
// "#,###." => "12,345"
57
// "#,###" => "12345,678"
58
// "#\u202F###,##" => "12 345,68"
59
// "#.###,###### => 12.345,678900
60
// "" (aka default format) => 12,345.67
61
//
62
// The highest precision allowed is 9 digits after the decimal symbol.
63
// There is also a version for integer number, FormatInteger(),
64
// which is convenient for calls within template.
65
func FormatFloat(format string, n float64) string {
66
	// Special cases:
67
	//   NaN = "NaN"
68
	//   +Inf = "+Infinity"
69
	//   -Inf = "-Infinity"
70
	if math.IsNaN(n) {
71
		return "NaN"
72
	}
73
	if n > math.MaxFloat64 {
74
		return "Infinity"
75
	}
76
	if n < (0.0 - math.MaxFloat64) {
77
		return "-Infinity"
78
	}
79

80
	// default format
81
	precision := 2
82
	decimalStr := "."
83
	thousandStr := ","
84
	positiveStr := ""
85
	negativeStr := "-"
86

87
	if len(format) > 0 {
88
		format := []rune(format)
89

90
		// If there is an explicit format directive,
91
		// then default values are these:
92
		precision = 9
93
		thousandStr = ""
94

95
		// collect indices of meaningful formatting directives
96
		formatIndx := []int{}
97
		for i, char := range format {
98
			if char != '#' && char != '0' {
99
				formatIndx = append(formatIndx, i)
100
			}
101
		}
102

103
		if len(formatIndx) > 0 {
104
			// Directive at index 0:
105
			//   Must be a '+'
106
			//   Raise an error if not the case
107
			// index: 0123456789
108
			//        +0.000,000
109
			//        +000,000.0
110
			//        +0000.00
111
			//        +0000
112
			if formatIndx[0] == 0 {
113
				if format[formatIndx[0]] != '+' {
114
					panic("RenderFloat(): invalid positive sign directive")
115
				}
116
				positiveStr = "+"
117
				formatIndx = formatIndx[1:]
118
			}
119

120
			// Two directives:
121
			//   First is thousands separator
122
			//   Raise an error if not followed by 3-digit
123
			// 0123456789
124
			// 0.000,000
125
			// 000,000.00
126
			if len(formatIndx) == 2 {
127
				if (formatIndx[1] - formatIndx[0]) != 4 {
128
					panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers")
129
				}
130
				thousandStr = string(format[formatIndx[0]])
131
				formatIndx = formatIndx[1:]
132
			}
133

134
			// One directive:
135
			//   Directive is decimal separator
136
			//   The number of digit-specifier following the separator indicates wanted precision
137
			// 0123456789
138
			// 0.00
139
			// 000,0000
140
			if len(formatIndx) == 1 {
141
				decimalStr = string(format[formatIndx[0]])
142
				precision = len(format) - formatIndx[0] - 1
143
			}
144
		}
145
	}
146

147
	// generate sign part
148
	var signStr string
149
	if n >= 0.000000001 {
150
		signStr = positiveStr
151
	} else if n <= -0.000000001 {
152
		signStr = negativeStr
153
		n = -n
154
	} else {
155
		signStr = ""
156
		n = 0.0
157
	}
158

159
	// split number into integer and fractional parts
160
	intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision])
161

162
	// generate integer part string
163
	intStr := strconv.FormatInt(int64(intf), 10)
164

165
	// add thousand separator if required
166
	if len(thousandStr) > 0 {
167
		for i := len(intStr); i > 3; {
168
			i -= 3
169
			intStr = intStr[:i] + thousandStr + intStr[i:]
170
		}
171
	}
172

173
	// no fractional part, we can leave now
174
	if precision == 0 {
175
		return signStr + intStr
176
	}
177

178
	// generate fractional part
179
	fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision]))
180
	// may need padding
181
	if len(fracStr) < precision {
182
		fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr
183
	}
184

185
	return signStr + intStr + decimalStr + fracStr
186
}
187

188
// FormatInteger produces a formatted number as string.
189
// See FormatFloat.
190
func FormatInteger(format string, n int) string {
191
	return FormatFloat(format, float64(n))
192
}
193

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.