summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comma.go8
-rw-r--r--comma_test.go9
-rw-r--r--ftoa.go25
-rw-r--r--ftoa_test.go9
-rw-r--r--si.go10
-rw-r--r--si_test.go23
6 files changed, 83 insertions, 1 deletions
diff --git a/comma.go b/comma.go
index 13611aa..520ae3e 100644
--- a/comma.go
+++ b/comma.go
@@ -76,6 +76,14 @@ func Commaf(v float64) string {
return buf.String()
}
+// CommafWithDigits works like the Commaf but limits the resulting
+// string to the given number of decimal places.
+//
+// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3
+func CommafWithDigits(f float64, decimals int) string {
+ return stripTrailingDigits(Commaf(f), decimals)
+}
+
// BigComma produces a string form of the given big.Int in base 10
// with commas after every three orders of magnitude.
func BigComma(b *big.Int) string {
diff --git a/comma_test.go b/comma_test.go
index 89daca5..c37a518 100644
--- a/comma_test.go
+++ b/comma_test.go
@@ -36,6 +36,15 @@ func TestCommas(t *testing.T) {
}.validate(t)
}
+func TestCommafWithDigits(t *testing.T) {
+ testList{
+ {"1.23, 0", CommafWithDigits(1.23, 0), "1"},
+ {"1.23, 1", CommafWithDigits(1.23, 1), "1.2"},
+ {"1.23, 2", CommafWithDigits(1.23, 2), "1.23"},
+ {"1.23, 3", CommafWithDigits(1.23, 3), "1.23"},
+ }.validate(t)
+}
+
func TestCommafs(t *testing.T) {
testList{
{"0", Commaf(0), "0"},
diff --git a/ftoa.go b/ftoa.go
index c76190b..1c62b64 100644
--- a/ftoa.go
+++ b/ftoa.go
@@ -1,6 +1,9 @@
package humanize
-import "strconv"
+import (
+ "strconv"
+ "strings"
+)
func stripTrailingZeros(s string) string {
offset := len(s) - 1
@@ -17,7 +20,27 @@ func stripTrailingZeros(s string) string {
return s[:offset+1]
}
+func stripTrailingDigits(s string, digits int) string {
+ if i := strings.Index(s, "."); i >= 0 {
+ if digits <= 0 {
+ return s[:i]
+ }
+ i++
+ if i+digits >= len(s) {
+ return s
+ }
+ return s[:i+digits]
+ }
+ return s
+}
+
// Ftoa converts a float to a string with no trailing zeros.
func Ftoa(num float64) string {
return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64))
}
+
+// FtoaWithDigits converts a float to a string but limits the resulting string
+// to the given number of decimal places, and no trailing zeros.
+func FtoaWithDigits(num float64, digits int) string {
+ return stripTrailingZeros(stripTrailingDigits(strconv.FormatFloat(num, 'f', 6, 64), digits))
+}
diff --git a/ftoa_test.go b/ftoa_test.go
index 276d411..e5076c4 100644
--- a/ftoa_test.go
+++ b/ftoa_test.go
@@ -17,6 +17,15 @@ func TestFtoa(t *testing.T) {
}.validate(t)
}
+func TestFtoaWithDigits(t *testing.T) {
+ testList{
+ {"1.23, 0", FtoaWithDigits(1.23, 0), "1"},
+ {"1.23, 1", FtoaWithDigits(1.23, 1), "1.2"},
+ {"1.23, 2", FtoaWithDigits(1.23, 2), "1.23"},
+ {"1.23, 3", FtoaWithDigits(1.23, 3), "1.23"},
+ }.validate(t)
+}
+
func BenchmarkFtoaRegexTrailing(b *testing.B) {
trailingZerosRegex := regexp.MustCompile(`\.?0+$`)
diff --git a/si.go b/si.go
index b24e481..ae659e0 100644
--- a/si.go
+++ b/si.go
@@ -93,6 +93,16 @@ func SI(input float64, unit string) string {
return Ftoa(value) + " " + prefix + unit
}
+// SIWithDigits works like SI but limits the resulting string to the
+// given number of decimal places.
+//
+// e.g. SIWithDigits(1000000, 0, "B") -> 1 MB
+// e.g. SIWithDigits(2.2345e-12, 2, "F") -> 2.23 pF
+func SIWithDigits(input float64, decimals int, unit string) string {
+ value, prefix := ComputeSI(input)
+ return FtoaWithDigits(value, decimals) + " " + prefix + unit
+}
+
var errInvalid = errors.New("invalid input")
// ParseSI parses an SI string back into the number and unit.
diff --git a/si_test.go b/si_test.go
index bc5bac6..e15fc69 100644
--- a/si_test.go
+++ b/si_test.go
@@ -94,6 +94,29 @@ func TestSI(t *testing.T) {
}
}
+func TestSIWithDigits(t *testing.T) {
+ tests := []struct {
+ name string
+ num float64
+ digits int
+ formatted string
+ }{
+ {"e-12", 2.234e-12, 0, "2 pF"},
+ {"e-12", 2.234e-12, 1, "2.2 pF"},
+ {"e-12", 2.234e-12, 2, "2.23 pF"},
+ {"e-12", 2.234e-12, 3, "2.234 pF"},
+ {"e-12", 2.234e-12, 4, "2.234 pF"},
+ }
+
+ for _, test := range tests {
+ got := SIWithDigits(test.num, test.digits, "F")
+ if got != test.formatted {
+ t.Errorf("On %v (%v), got %v, wanted %v",
+ test.name, test.num, got, test.formatted)
+ }
+ }
+}
+
func BenchmarkParseSI(b *testing.B) {
for i := 0; i < b.N; i++ {
ParseSI("2.2346ZB")