String 如何fmt.Printf一个带有数千个逗号的整数

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

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("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
                }
    }
}