Skip to content

Instantly share code, notes, and snippets.

@suzujun
Last active November 2, 2018 01:17
Show Gist options
  • Save suzujun/807935ad16fb61f9e73626fd20f93c64 to your computer and use it in GitHub Desktop.
Save suzujun/807935ad16fb61f9e73626fd20f93c64 to your computer and use it in GitHub Desktop.
func comma(v int64) string {
sign := ""
// Min int64 can't be negated to a usable value, so it has to be special cased.
if v == math.MinInt64 {
return "-9,223,372,036,854,775,808"
}
if v < 0 {
sign = "-"
v = 0 - v
}
parts := []string{"", "", "", "", "", "", ""}
j := len(parts) - 1
for v > 999 {
parts[j] = strconv.FormatInt(v%1000, 10)
switch len(parts[j]) {
case 2:
parts[j] = "0" + parts[j]
case 1:
parts[j] = "00" + parts[j]
}
v = v / 1000
j--
}
parts[j] = strconv.Itoa(int(v))
return sign + strings.Join(parts[j:], ",")
}
// use string.builder
func comma2(v int64) string {
sign := ""
// Min int64 can't be negated to a usable value, so it has to be special cased.
if v == math.MinInt64 {
return "-9,223,372,036,854,775,808"
}
if v < 0 {
sign = "-"
v = 0 - v
}
parts := make([]int16, 7)
j := len(parts) - 1
for v > 999 {
parts[j] = int16(v % 1000)
v = v / 1000
j--
}
parts[j] = int16(v)
var buf strings.Builder
buf.Grow(26)
if len(sign) > 0 {
buf.WriteString("-")
}
var start bool
for _, v := range parts {
if start {
buf.WriteString(",")
}
if v == 0 && start {
buf.WriteString("000")
} else if v < 10 {
if start {
buf.WriteString("00")
}
buf.WriteString(strconv.Itoa(int(v)))
} else if v < 100 {
if start {
buf.WriteString("0")
}
buf.WriteString(strconv.Itoa(int(v)))
} else {
buf.WriteString(strconv.Itoa(int(v)))
}
if v > 0 {
start = true
}
}
return buf.String() //sign + strings.Join(parts[j:], ",")
}
// use string.builder and sprintf
func comma3(v int64) string {
sign := ""
// Min int64 can't be negated to a usable value, so it has to be special cased.
if v == math.MinInt64 {
return "-9,223,372,036,854,775,808"
}
if v < 0 {
sign = "-"
v = 0 - v
}
parts := make([]int16, 7)
j := len(parts) - 1
for v > 999 {
parts[j] = int16(v % 1000)
v = v / 1000
j--
}
parts[j] = int16(v)
var buf strings.Builder
buf.Grow(26)
if len(sign) > 0 {
buf.WriteString("-")
}
var start bool
for _, v := range parts {
if start {
buf.WriteString(",")
}
if v > 0 && !start {
buf.WriteString(strconv.Itoa(int(v)))
start = true
} else if v == 0 && start || v > 0 {
buf.WriteString(fmt.Sprintf("%03d", v))
start = true
}
}
return buf.String()
}
// -------------------------
// bench
// -------------------------
func BenchmarkCommaStringJoin(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
comma(math.MaxInt64)
}
}
func BenchmarkCommaStringBuilder(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
comma2(math.MaxInt64)
}
}
func BenchmarkCommaSprintf(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
comma3(math.MaxInt64)
}
}
@suzujun
Copy link
Author

suzujun commented Nov 2, 2018

ベンチ結果

BenchmarkCommaStringJoin-8      	 3000000	       405 ns/op	      83 B/op	       8 allocs/op
BenchmarkCommaStringBuilder-8   	 5000000	       384 ns/op	      48 B/op	       6 allocs/op
BenchmarkCommaSprintf-8         	 1000000	      1061 ns/op	      70 B/op	      13 allocs/op
PASS```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment