String 如何fmt.Printf一个带有数千个逗号的整数
Go的String 如何fmt.Printf一个带有数千个逗号的整数,string,go,formatting,printf,String,Go,Formatting,Printf,Go的fmt.Printf支持输出带有数千个逗号的数字吗 fmt.Printf(“%d”,1000)输出1000,我可以指定什么格式输出1000 似乎没有提到逗号,我也无法立即在中看到任何内容。没有一个fmt打印谓词支持数千个分隔符 我写了一些关于人类表现的问题 示例结果: 0 -> 0 100 -> 100 1000 -> 1,000 1000000000 -> 1,000,000,000 -100000 -> -100,000 用法示例: fmt.Printf
fmt.Printf
支持输出带有数千个逗号的数字吗
fmt.Printf(“%d”,1000)
输出1000
,我可以指定什么格式输出1000
似乎没有提到逗号,我也无法立即在中看到任何内容。没有一个fmt打印谓词支持数千个分隔符 我写了一些关于人类表现的问题 示例结果:
0 -> 0
100 -> 100
1000 -> 1,000
1000000000 -> 1,000,000,000
-100000 -> -100,000
用法示例:
fmt.Printf("You owe $%s.\n", humanize.Comma(6582491))
我在Github发布了一个函数的Go代码段,根据用户指定的千位分隔符、十进制分隔符和十进制精度来呈现一个数字(float64或int) 用法:s:=RenderFloat(格式,n) format参数说明如何呈现数字n。 给定n=12345.6789的格式字符串示例: "#,###.##" => "12,345.67" "#,###." => "12,345" "#,###" => "12345,678" “#\u202F#####,##”=>”12 345,67" "#.###,###### => 12.345,678900 “”(也称为默认格式)=>12345.67
这是一个函数,它使用整数和分组分隔符,并返回一个用指定分隔符分隔的字符串。我已尝试优化效率,在紧循环中不使用字符串串联或mod/division。从我的分析来看,它的速度是humanize.Commas实现的两倍多(~680ns vs 1642ns)在我的Mac上。我是新手,希望看到更快的实现 用法:s:=NumberToString(n int,sep符文) 示例 说明如何使用不同的分隔符(“,”vs“”),并使用int值范围进行验证 s:=NumberToString(12345678,',') =>“12345678” s:=NumberToString(12345678,“”) =>“12345 678” s:=NumberToString(-9223372036854775807,,) =>“-9223372036854775807” 功能实现
func NumberToString(n int, sep rune) string {
s := strconv.Itoa(n)
startOffset := 0
var buff bytes.Buffer
if n < 0 {
startOffset = 1
buff.WriteByte('-')
}
l := len(s)
commaIndex := 3 - ((l - startOffset) % 3)
if (commaIndex == 3) {
commaIndex = 0
}
for i := startOffset; i < l; i++ {
if (commaIndex == 3) {
buff.WriteRune(sep)
commaIndex = 0
}
commaIndex++
buff.WriteByte(s[i])
}
return buff.String()
}
func NumberToString(n int,sep rune)字符串{
s:=strconv.Itoa(n)
startOffset:=0
var buff bytes.Buffer
如果n<0{
startOffset=1
buff.WriteByte('-'))
}
l:=len(s)
commaIndex:=3-((l-开始设置)%3)
如果(commaIndex==3){
commaIndex=0
}
对于i:=startOffset;i
如果您不想使用库(无论出于何种原因),我将其简化。它似乎可以工作,并且可以使用任何指定的符文作为分隔符:
import (
"strconv"
)
func delimitNumeral(i int, delim rune) string {
src := strconv.Itoa(i)
strLen := utf8.RuneCountInString(src)
outStr := ""
digitCount := 0
for i := strLen - 1; i >= 0; i-- {
outStr = src[i:i+1] + outStr
if digitCount == 2 {
outStr = string(delim) + outStr
digitCount = 0
} else {
digitCount++
}
}
return outStr
}
注意:进一步测试后,此功能无法完美运行。我建议使用@IvanTung发布的解决方案,并欢迎任何能让我的解决方案完美运行的人进行任何编辑。使用..它有一组帮助程序来处理这些事情。此外还有MiB、MB等字节。Fo回复:我在中发布了此实用程序,并进行了更多自定义,请参阅
包不支持分组小数 我们必须自己实现一个(或使用现有的一个) 代码 下面是一个紧凑且非常有效的解决方案(请参见后面的解释): 试穿一下 输出:
0 = 0
0 = 0
1 = 1
-1 = -1
12 = 12
-12 = -12
123 = 123
-123 = -123
1234 = 1,234
-1234 = -1,234
123456789 = 123,456,789
-123456789 = -123,456,789
1,000
-1,000,000,000
说明:
基本上,Format()
函数所做的是在不分组的情况下对数字进行格式化,然后创建一个足够大的其他切片,并在必要时复制数字的数字,插入逗号(,“
)分组符号(如果有更多数字,则在3的数字组之后)同时注意要保留的负号
输出的长度:
基本上是输入的长度加上要插入的分组符号的数量。分组符号的数量为:
numOfCommas = (numOfDigits - 1) / 3
由于输入字符串是一个只能包含数字('0..9'
)和可选的负号('-'
)的数字,因此在UTF-8编码中,字符仅以1:1的方式映射到字节(这是Go在内存中存储字符串的方式)。因此,我们可以简单地使用字节而不是符文。因此,位数是输入字符串长度,如果数字为负数,可以选择减去1
:
numOfDigits := len(in)
if n < 0 {
numOfDigits-- // First character is the - sign (not a digit)
}
因此,输出片将是:
out := make([]byte, len(in)+numOfCommas)
处理负号字符:
如果数字为负数,我们只需对输入字符串进行切片,将其从处理中排除,然后手动将符号位复制到输出:
if n < 0 {
in, out[0] = in[1:], '-'
}
基本上,它通过递归调用处理负数:如果负数,则使用绝对(正)值调用自身(递归),并使用“-”
字符串作为结果的前缀
使用append()
切片
下面是另一个使用内置函数和切片操作的版本。稍微容易理解,但性能不太好:
func Format3(n int64) string {
if n < 0 {
return "-" + Format3(-n)
}
in := []byte(strconv.FormatInt(n, 10))
var out []byte
if i := len(in) % 3; i != 0 {
if out, in = append(out, in[:i]...), in[i:]; len(in) > 0 {
out = append(out, ',')
}
}
for len(in) > 0 {
if out, in = append(out, in[:3]...), in[3:]; len(in) > 0 {
out = append(out, ',')
}
}
return string(out)
}
func Format3(n int64)字符串{
如果n<0{
返回“-”+Format3(-n)
}
in:=[]字节(strconv.FormatInt(n,10))
var out[]字节
如果i:=len(in)%3;i!=0{
如果out,in=append(out,in[:i]…),in[i:];len(in)>0{
out=追加(out,,)
}
}
对于len(in)>0{
如果out,in=append(out,in[:3]…),in[3];len(in)>0{
out=追加(out,,)
}
}
返回字符串(输出)
}
第一个
if
语句处理第一个可选的“不完整”组,如果存在该组,则该组少于3位数字,随后的for
循环处理其余部分,在每次迭代中复制3位数字并附加逗号(,'
)如果有更多的数字,则分组符号。这里有一个使用正则表达式的简单函数:
import (
"regexp"
)
func formatCommas(num int) string {
str := fmt.Sprintf("%d", num)
re := regexp.MustCompile("(\\d+)(\\d{3})")
for n := ""; n != str; {
n = str
str = re.ReplaceAllString(str, "$1,$2")
}
return str
}
例如:
fmt.Println(formatCommas(1000))
fmt.Println(formatCommas(-1000000000))
输出:
0 = 0
0 = 0
1 = 1
-1 = -1
12 = 12
-12 = -12
123 = 123
-123 = -123
1234 = 1,234
-1234 = -1,234
123456789 = 123,456,789
-123456789 = -123,456,789
1,000
-1,000,000,000
导入(“fmt”;“字符串”)
func逗号(s字符串)字符串{
如果len(s)用于使用中任何语言的本地化格式进行打印:
包装人性化可以发挥神奇作用!参考
import (
"regexp"
)
func formatCommas(num int) string {
str := fmt.Sprintf("%d", num)
re := regexp.MustCompile("(\\d+)(\\d{3})")
for n := ""; n != str; {
n = str
str = re.ReplaceAllString(str, "$1,$2")
}
return str
}
fmt.Println(formatCommas(1000))
fmt.Println(formatCommas(-1000000000))
1,000
-1,000,000,000
import ("fmt"; "strings")
func commas(s string) string {
if len(s) <= 3 {
return s
} else {
return commas(s[0:len(s)-3]) + "," + s[len(s)-3:]
}
}
func toString(f float64) string {
parts := strings.Split(fmt.Sprintf("%.2f", f), ".")
if parts[0][0] == '-' {
return "-" + commas(parts[0][1:]) + "." + parts[1]
}
return commas(parts[0]) + "." + parts[1]
}
package main
import (
"golang.org/x/text/language"
"golang.org/x/text/message"
)
func main() {
p := message.NewPrinter(language.English)
p.Printf("%d\n", 1000)
// Output:
// 1,000
}
go get -u github.com/dustin/go-humanize
package main
import (
"fmt"
"github.com/dustin/go-humanize"
)
func main() {
fmt.Println(humanize.Commaf(float64(123456789)));
fmt.Println(humanize.Commaf(float64(-1000000000)));
fmt.Println(humanize.Commaf(float64(-100000.005)));
fmt.Println(humanize.Commaf(float64(100000.000)));
}
go run main.go
123,456,789
-1,000,000,000
-100,000.005
100,000
+---------------------+-------------------------------------------+--------------+
| Author | Description | Result |
|---------------------|-------------------------------------------|--------------|
| myself | dividing by 1,000 and appending groups | 3,472 ns/op |
| myself | inserting commas to digit groups | 2,662 ns/op |
| @icza | collecting digit by digit to output array | 1,695 ns/op |
| @dolmen | copying digit groups to output array | 1,797 ns/op |
| @Ivan Tung | writing digit by digit to buffer | 2,753 ns/op |
| @jchavannes | inserting commas using a regexp | 63,995 ns/op |
| @Steffi Keran Rani, | using github.com/dustin/go-humanize | 3,525 ns/op |
| @abourget, @Dustin | | |
| @dolmen | using golang.org/x/text/message | 12,511 ns/op |
+---------------------+-------------------------------------------+--------------+
n:="3478686" // your number as a string
thousands.Separate(n, "en") // adds thousands separators. the second argument sets the language mode.
package main
import (
"fmt"
)
func IntComma(i int) string {
if (i < 0) {
return "-" + IntComma(-i)
}
if (i < 1000) {
return fmt.Sprintf("%d",i)
}
return IntComma(i / 1000) + "," + fmt.Sprintf("%03d",i % 1000)
}
func main() {
fmt.Println(IntComma(1234567891234567))
}
func IntCommaB(num int) string {
str := strconv.Itoa(num)
l_str := len(str)
digits := l_str
if num < 0 {
digits--
}
commas := (digits + 2) / 3 - 1
l_buf := l_str + commas
var sbuf [32]byte // pre allocate buffer at stack rather than make([]byte,n)
buf := sbuf[0:l_buf]
// copy str from the end
for s_i, b_i, c3 := l_str-1, l_buf-1, 0; ; {
buf[b_i] = str[s_i]
if s_i == 0 {
return string(buf)
}
s_i--
b_i--
// insert comma every 3 chars
c3++
if c3 == 3 && (s_i > 0 || num>0) {
buf[b_i] = ','
b_i--
c3 = 0
}
}
}