Skip to content

Commit 41f8089

Browse files
brampdustin
authored andcommittedApr 21, 2018
Add a few methods for limiting the number of decimal places outputted. #18
1 parent bb3d318 commit 41f8089

File tree

6 files changed

+83
-1
lines changed

6 files changed

+83
-1
lines changed
 

‎comma.go

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ func Commaf(v float64) string {
7676
return buf.String()
7777
}
7878

79+
// CommafWithDigits works like the Commaf but limits the resulting
80+
// string to the given number of decimal places.
81+
//
82+
// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3
83+
func CommafWithDigits(f float64, decimals int) string {
84+
return stripTrailingDigits(Commaf(f), decimals)
85+
}
86+
7987
// BigComma produces a string form of the given big.Int in base 10
8088
// with commas after every three orders of magnitude.
8189
func BigComma(b *big.Int) string {

‎comma_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ func TestCommas(t *testing.T) {
3636
}.validate(t)
3737
}
3838

39+
func TestCommafWithDigits(t *testing.T) {
40+
testList{
41+
{"1.23, 0", CommafWithDigits(1.23, 0), "1"},
42+
{"1.23, 1", CommafWithDigits(1.23, 1), "1.2"},
43+
{"1.23, 2", CommafWithDigits(1.23, 2), "1.23"},
44+
{"1.23, 3", CommafWithDigits(1.23, 3), "1.23"},
45+
}.validate(t)
46+
}
47+
3948
func TestCommafs(t *testing.T) {
4049
testList{
4150
{"0", Commaf(0), "0"},

‎ftoa.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package humanize
22

3-
import "strconv"
3+
import (
4+
"strconv"
5+
"strings"
6+
)
47

58
func stripTrailingZeros(s string) string {
69
offset := len(s) - 1
@@ -17,7 +20,27 @@ func stripTrailingZeros(s string) string {
1720
return s[:offset+1]
1821
}
1922

23+
func stripTrailingDigits(s string, digits int) string {
24+
if i := strings.Index(s, "."); i >= 0 {
25+
if digits <= 0 {
26+
return s[:i]
27+
}
28+
i++
29+
if i+digits >= len(s) {
30+
return s
31+
}
32+
return s[:i+digits]
33+
}
34+
return s
35+
}
36+
2037
// Ftoa converts a float to a string with no trailing zeros.
2138
func Ftoa(num float64) string {
2239
return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64))
2340
}
41+
42+
// FtoaWithDigits converts a float to a string but limits the resulting string
43+
// to the given number of decimal places, and no trailing zeros.
44+
func FtoaWithDigits(num float64, digits int) string {
45+
return stripTrailingZeros(stripTrailingDigits(strconv.FormatFloat(num, 'f', 6, 64), digits))
46+
}

‎ftoa_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ func TestFtoa(t *testing.T) {
1717
}.validate(t)
1818
}
1919

20+
func TestFtoaWithDigits(t *testing.T) {
21+
testList{
22+
{"1.23, 0", FtoaWithDigits(1.23, 0), "1"},
23+
{"1.23, 1", FtoaWithDigits(1.23, 1), "1.2"},
24+
{"1.23, 2", FtoaWithDigits(1.23, 2), "1.23"},
25+
{"1.23, 3", FtoaWithDigits(1.23, 3), "1.23"},
26+
}.validate(t)
27+
}
28+
2029
func BenchmarkFtoaRegexTrailing(b *testing.B) {
2130
trailingZerosRegex := regexp.MustCompile(`\.?0+$`)
2231

‎si.go

+10
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ func SI(input float64, unit string) string {
9393
return Ftoa(value) + " " + prefix + unit
9494
}
9595

96+
// SIWithDigits works like SI but limits the resulting string to the
97+
// given number of decimal places.
98+
//
99+
// e.g. SIWithDigits(1000000, 0, "B") -> 1 MB
100+
// e.g. SIWithDigits(2.2345e-12, 2, "F") -> 2.23 pF
101+
func SIWithDigits(input float64, decimals int, unit string) string {
102+
value, prefix := ComputeSI(input)
103+
return FtoaWithDigits(value, decimals) + " " + prefix + unit
104+
}
105+
96106
var errInvalid = errors.New("invalid input")
97107

98108
// ParseSI parses an SI string back into the number and unit.

‎si_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,29 @@ func TestSI(t *testing.T) {
9494
}
9595
}
9696

97+
func TestSIWithDigits(t *testing.T) {
98+
tests := []struct {
99+
name string
100+
num float64
101+
digits int
102+
formatted string
103+
}{
104+
{"e-12", 2.234e-12, 0, "2 pF"},
105+
{"e-12", 2.234e-12, 1, "2.2 pF"},
106+
{"e-12", 2.234e-12, 2, "2.23 pF"},
107+
{"e-12", 2.234e-12, 3, "2.234 pF"},
108+
{"e-12", 2.234e-12, 4, "2.234 pF"},
109+
}
110+
111+
for _, test := range tests {
112+
got := SIWithDigits(test.num, test.digits, "F")
113+
if got != test.formatted {
114+
t.Errorf("On %v (%v), got %v, wanted %v",
115+
test.name, test.num, got, test.formatted)
116+
}
117+
}
118+
}
119+
97120
func BenchmarkParseSI(b *testing.B) {
98121
for i := 0; i < b.N; i++ {
99122
ParseSI("2.2346ZB")

0 commit comments

Comments
 (0)
Please sign in to comment.