如何使用 fmt.Printf 函数在整数中添加千位分隔符

huangapple go评论79阅读模式
英文:

How to fmt.Printf an integer with thousands comma

问题

Go的fmt.Printf支持输出带有千位分隔符的数字吗?

fmt.Printf("%d", 1000)输出1000,我可以指定什么格式来输出1,000呢?

文档似乎没有提到逗号,我在源代码中也没有立即看到任何相关内容。

英文:

Does Go's fmt.Printf support outputting a number with the thousands comma?

fmt.Printf("%d", 1000) outputs 1000, what format can I specify to output 1,000 instead?

The docs don't seem to mention commas, and I couldn't immediately see anything in the source.

答案1

得分: 138

使用golang.org/x/text/message来使用本地化格式打印任何语言的内容,使用Unicode CLDR

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)

	// 输出:
	// 1,000
}
英文:

Use golang.org/x/text/message to print using localized formatting for any language in the Unicode CLDR:

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
}

答案2

得分: 58

我写了一个库humanize来处理这个问题,以及其他一些人类表示的问题。

示例结果:

0 -> 0
100 -> 100
1000 -> 1,000
1000000000 -> 1,000,000,000
-100000 -> -100,000

示例用法:

fmt.Printf("你欠我$%s。\n", humanize.Comma(6582491))
英文:

I wrote a library for this as well as a few other human-representation concerns.

Example results:

0 -> 0
100 -> 100
1000 -> 1,000
1000000000 -> 1,000,000,000
-100000 -> -100,000

Example Usage:

fmt.Printf("You owe $%s.\n", humanize.Comma(6582491))

答案3

得分: 32

没有一个 fmt 打印动词支持千位分隔符。

英文:

None of the fmt print verbs support thousands separators.

答案4

得分: 22

**前言:**我在github.com/icza/gox上发布了这个带有更多自定义功能的实用程序,请参阅fmtx.FormatInt()


fmt包不支持对小数进行分组。

我们需要自己实现一个(或使用现有的)。

代码

这是一个紧凑且非常高效的解决方案(详细解释见下文):

Go Playground上尝试一下。

func Format(n int64) string {
	in := strconv.FormatInt(n, 10)
	numOfDigits := len(in)
	if n < 0 {
		numOfDigits-- // 第一个字符是负号(不是数字)
	}
	numOfCommas := (numOfDigits - 1) / 3

	out := make([]byte, len(in)+numOfCommas)
	if n < 0 {
		in, out[0] = in[1:], '-'
	}

	for i, j, k := len(in)-1, len(out)-1, 0; ; i, j = i-1, j-1 {
		out[j] = in[i]
		if i == 0 {
			return string(out)
		}
		if k++; k == 3 {
			j, k = j-1, 0
			out[j] = ','
		}
	}
}

测试代码:

for _, v := range []int64{0, 1, 12, 123, 1234, 123456789} {
	fmt.Printf("%10d = %12s\n", v, Format(v))
	fmt.Printf("%10d = %12s\n", -v, Format(-v))
}

输出结果:

         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

解释:

Format()函数的基本功能是对数字进行格式化,不进行分组,然后创建一个足够大的字节切片,并在必要时(如果有更多的数字)将数字的每个组的3个数字之后插入逗号(,)分组符号,同时确保负号被保留。

输出的长度:

基本上是输入的长度加上要插入的分组符号的数量。分组符号的数量为:

numOfCommas = (numOfDigits - 1) / 3

由于输入字符串是一个只包含数字(0..9)和可选负号(-)的数字,字符在UTF-8编码中被简单地映射为字节(这是Go在内存中存储字符串的方式)。因此,我们可以简单地使用字节而不是符文进行操作。因此,数字的位数是输入字符串的长度,如果数字是负数,则可选减去1

numOfDigits := len(in)
if n < 0 {
	numOfDigits-- // 第一个字符是负号(不是数字)
}

因此,分组符号的数量为:

numOfCommas := (numOfDigits - 1) / 3

因此,输出切片将是:

out := make([]byte, len(in)+numOfCommas)

处理负号字符:

如果数字是负数,我们只需切片输入字符串以排除它,并将符号位手动复制到输出中:

if n < 0 {
	in, out[0] = in[1:], '-'
}

因此,函数的其余部分不需要知道/关心可选的负号字符。

函数的其余部分是一个for循环,它只是将数字的字节(数字)从输入字符串复制到输出中,如果有更多数字,则在每个3个数字的组之后插入一个分组符号(,)。循环向下进行,因此更容易跟踪3个数字的组。完成后(没有更多数字),将输出字节切片作为string返回。

变体

使用递归处理负数

如果您更关心可读性而不是效率,您可能会喜欢这个版本:

func Format2(n int64) string {
	if n < 0 {
		return "-" + Format2(-n)
	}

	in := strconv.FormatInt(n, 10)
	numOfCommas := (len(in) - 1) / 3

	out := make([]byte, len(in)+numOfCommas)

	for i, j, k := len(in)-1, len(out)-1, 0; ; i, j = i-1, j-1 {
		out[j] = in[i]
		if i == 0 {
			return string(out)
		}
		if k++; k == 3 {
			j, k = j-1, 0
			out[j] = ','
		}
	}
}

基本上,这个版本使用递归调用处理负数:如果数字是负数,则使用绝对值(正数)调用自身(递归),并在结果前面添加一个"-"字符串。

使用append()切片

这是另一个版本,使用内置的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)
}

第一个if语句处理第一个可选的、不足3位数字的“不完整”组,如果存在的话,并且随后的for循环处理剩下的部分,每次迭代复制3个数字并追加逗号(,)分组符号(如果还有更多数字)。

英文:

Foreword: I released this utility with more customization in github.com/icza/gox, see fmtx.FormatInt().


The fmt package does not support grouping decimals.

We have to implement one ourselves (or use an existing one).

The Code

Here is a compact and really efficient solution (see explanation after):

Try it on the Go Playground.

func Format(n int64) string {
	in := strconv.FormatInt(n, 10)
	numOfDigits := len(in)
	if n < 0 {
		numOfDigits-- // First character is the - sign (not a digit)
	}
	numOfCommas := (numOfDigits - 1) / 3

	out := make([]byte, len(in)+numOfCommas)
	if n < 0 {
		in, out[0] = in[1:], '-'
	}

	for i, j, k := len(in)-1, len(out)-1, 0; ; i, j = i-1, j-1 {
		out[j] = in[i]
		if i == 0 {
			return string(out)
		}
		if k++; k == 3 {
			j, k = j-1, 0
			out[j] = ','
		}
	}
}

Testing it:

for _, v := range []int64{0, 1, 12, 123, 1234, 123456789} {
	fmt.Printf("%10d = %12s\n", v, Format(v))
	fmt.Printf("%10d = %12s\n", -v, Format(-v))
}

Output:

         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

Explanation:

Basically what the Format() function does is it formats the number without grouping, then creates a big enough other slice and copies the digits of the number inserting comma (',') grouping symbol when necessary (after groups of digits of 3 if there are more digits) meanwhile taking care of the negative sign to be preserved.

The length of the output:

It is basically the length of the input plus the number of grouping signs to be inserted. The number of grouping signs is:

numOfCommas = (numOfDigits - 1) / 3

Since the input string is a number which may only contain digits ('0..9') and optionally a negative sign ('-'), the characters are simply mapped to bytes in a 1-to-1 fashion in UTF-8 encoding (this is how Go stores strings in memory). So we can simply work with bytes instead of runes. So the number of digits is the input string length, optionally minus 1 if the number is negative:

numOfDigits := len(in)
if n < 0 {
	numOfDigits-- // First character is the - sign (not a digit)
}

And therefore the number of grouping signs:

numOfCommas := (numOfDigits - 1) / 3

Therefore the output slice will be:

out := make([]byte, len(in)+numOfCommas)

Handling the negative sign character:

If the number is negative, we simply slice the input string to exclude it from processing and we manually copy the sign bit to the output:

if n < 0 {
	in, out[0] = in[1:], '-'
}

And therefore the rest of the function does not need to know/care about the optional negative sign character.

The rest of the function is a for loop which just copies the bytes (digits) of the number from the input string to the output, inserting a grouping sign (',') after every group of 3 digits if there are more digits. The loop goes downward so it's easier to track the groups of 3 digits. Once done (no more digits), the output byte slice is returned as a string.

Variations

Handling negative with recursion

If you're less concerned with efficiency and more about readability, you might like this version:

func Format2(n int64) string {
	if n < 0 {
		return "-" + Format2(-n)
	}

	in := strconv.FormatInt(n, 10)
	numOfCommas := (len(in) - 1) / 3

	out := make([]byte, len(in)+numOfCommas)

	for i, j, k := len(in)-1, len(out)-1, 0; ; i, j = i-1, j-1 {
		out[j] = in[i]
		if i == 0 {
			return string(out)
		}
		if k++; k == 3 {
			j, k = j-1, 0
			out[j] = ','
		}
	}
}

Basically this handles negative numbers with a recursive call: if the number is negative, calls itself (recursive) with the absolute (positive) value and prepends the result with a "-" string.

With append() slices

Here's another version using the builtin append() function and slice operations. Somewhat easier to understand but not so good performance-wise:

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)
}

The first if statement takes care of the first optional, "incomplete" group which is less than 3 digits if exists, and the subsequent for loop handles the rest, copying 3 digits in each iteration and appending a comma (',') grouping sign if there are more digits.

答案5

得分: 16

我在Github上发布了一个Go代码片段,用于根据用户指定的千位分隔符、小数点分隔符和小数精度来渲染一个数字(float64或int)。

https://gist.github.com/gorhill/5285193

<pre>
用法:s := RenderFloat(format, n)

format参数告诉如何渲染数字n。

格式字符串的示例,给定n = 12345.6789:

"#,###.##" => "12,345.67"
"#,###." => "12,345"
"#,###" => "12345,678"
"#\u202F###,##" => "12 345,67"
"#.###,###### => 12.345,678900
""(也称为默认格式) => 12,345.67
</pre>

英文:

I published a Go snippet over at Github of a function to render a number (float64 or int) according to user-specified thousand separator, decimal separator and decimal precision.

https://gist.github.com/gorhill/5285193

<pre>
Usage: s := RenderFloat(format, n)

The format parameter tells how to render the number n.

Examples of format strings, given n = 12345.6789:

"#,###.##" => "12,345.67"
"#,###." => "12,345"
"#,###" => "12345,678"
"#\u202F###,##" => "12 345,67"
"#.###,###### => 12.345,678900
"" (aka default format) => 12,345.67
</pre>

答案6

得分: 10

这是一个函数,它接受一个整数和分组分隔符,并返回一个用指定分隔符分隔的字符串。我尝试优化效率,紧密循环中没有字符串连接或模除运算。根据我的分析,在我的Mac上,它比humanize.Commas实现(约680纳秒对1642纳秒)快两倍以上。我是Go的新手,很想看到更快的实现!

用法:s := NumberToString(n int, sep rune)

示例

演示了使用不同的分隔符(',' vs ' '),并通过int值范围进行验证。

s:= NumberToString(12345678, ',')

=> "12,345,678"

s:= NumberToString(12345678, ' ')

=> "12 345 678"

s: = NumberToString(-9223372036854775807, ',')

=> "-9,223,372,036,854,775,807"

函数实现

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()
}
英文:

Here is a function that takes an integer and grouping separator and returns a string delimited with the specified separator. I have tried to optimize for efficiency, no string concatenation or mod/division in the tight loop. From my profiling it is more than twice as fast as the humanize.Commas implementation (~680ns vs 1642ns) on my Mac. I am new to Go, would love to see faster implementations!

Usage: s := NumberToString(n int, sep rune)

Examples

Illustrates using different separator (',' vs ' '), verified with int value range.

s:= NumberToString(12345678, ',')

=> "12,345,678"

s:= NumberToString(12345678, ' ')

=> "12 345 678"

s: = NumberToString(-9223372036854775807, ',')

=> "-9,223,372,036,854,775,807"

Function Implementation

func NumberToString(n int, sep rune) string {

    s := strconv.Itoa(n)

    startOffset := 0
    var buff bytes.Buffer

    if n &lt; 0 {
	    startOffset = 1
	    buff.WriteByte(&#39;-&#39;)
    }


    l := len(s)

    commaIndex := 3 - ((l - startOffset) % 3) 

    if (commaIndex == 3) {
	    commaIndex = 0
    }

    for i := startOffset; i &lt; l; i++ {

	    if (commaIndex == 3) {
	    	buff.WriteRune(sep)
		    commaIndex = 0
	    }
	    commaIndex++

	    buff.WriteByte(s[i])
    }

    return buff.String()
}

答案7

得分: 9

这是一个使用正则表达式的简单函数:

import (
	&quot;regexp&quot;
)

func formatCommas(num int) string {
	str := fmt.Sprintf(&quot;%d&quot;, num)
	re := regexp.MustCompile(&quot;(\\d+)(\\d{3})&quot;)
	for n := &quot;&quot;; n != str; {
		n = str
		str = re.ReplaceAllString(str, &quot;$1,$2&quot;)
	}
	return str
}

示例:

fmt.Println(formatCommas(1000))
fmt.Println(formatCommas(-1000000000))

输出:

1,000
-1,000,000,000

https://play.golang.org/p/vnsAV23nUXv

英文:

Here's a simple function using regex:

import (
	&quot;regexp&quot;
)

func formatCommas(num int) string {
	str := fmt.Sprintf(&quot;%d&quot;, num)
	re := regexp.MustCompile(&quot;(\\d+)(\\d{3})&quot;)
	for n := &quot;&quot;; n != str; {
		n = str
		str = re.ReplaceAllString(str, &quot;$1,$2&quot;)
	}
	return str
}

Example:

fmt.Println(formatCommas(1000))
fmt.Println(formatCommas(-1000000000))

Output:

1,000
-1,000,000,000

https://play.golang.org/p/vnsAV23nUXv

答案8

得分: 8

我对之前回答中提供的解决方案的性能产生了兴趣,并编写了对它们进行基准测试的测试,其中包括两个我自己的代码片段。以下结果是在2018年的MacBook上测量的,i7 2.6GHz:

+---------------------+-------------------------------------------+--------------+
|       作者          |                描述                       |    结果      |
|---------------------|-------------------------------------------|--------------|
| 我自己              | 除以1,000并附加组                          |  3,472 ns/op |
| 我自己              | 插入逗号到数字组                          |  2,662 ns/op |
| @icza               | 逐位收集到输出数组                        |  1,695 ns/op |
| @dolmen             | 复制数字组到输出数组                       |  1,797 ns/op |
| @Ivan Tung          | 逐位写入缓冲区                            |  2,753 ns/op |
| @jchavannes         | 使用正则表达式插入逗号                     | 63,995 ns/op |
| @Steffi Keran Rani, | 使用github.com/dustin/go-humanize          |  3,525 ns/op |
|  @abourget, @Dustin |                                           |              |
| @dolmen             | 使用golang.org/x/text/message              | 12,511 ns/op |
+---------------------+-------------------------------------------+--------------+
  • 如果你想要最快的解决方案,请使用@icza的代码片段。尽管它是逐位处理而不是每三位一组处理,但它被证明是最快的。
  • 如果你想要最短的合理代码片段,请查看下面的我的代码。它增加了最快解决方案的一半以上的时间,但代码长度缩短了三倍。
  • 如果你想要一个一行代码的解决方案,并且不介意使用外部库,请选择github.com/dustin/go-humanize。它比最快的解决方案慢两倍以上,但该库可能会帮助你进行其他格式化。
  • 如果你想要本地化输出,请选择golang.org/x/text/message。它比最快的解决方案慢七倍,但匹配消费者的语言的奢侈性是有代价的。

其他手写的解决方案也很快,选择任何一个都不会后悔,除了使用正则表达式。使用正则表达式需要最短的代码片段,但性能如此糟糕,不值得。

我对这个主题的贡献,你可以在playground上尝试运行

func formatInt(number int) string {
	output := strconv.Itoa(number)
	startOffset := 3
	if number < 0 {
		startOffset++
	}
	for outputIndex := len(output); outputIndex > startOffset; {
		outputIndex -= 3
		output = output[:outputIndex] + "," + output[outputIndex:]
	}
	return output
}
英文:

I got interested in the performance of solutions offered in earlier answers and wrote tests with benchmarks for them, including two code snippets of mine. The following results were measured on MacBook 2018, i7 2.6GHz:

+---------------------+-------------------------------------------+--------------+
|       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 |
+---------------------+-------------------------------------------+--------------+
  • If you want the fastest solution, grab @icza's code snippet. Although it goes digit by digit and not by groups of three digits, it emerged as the fastest.
  • If you want the shortest reasonable code snippet, look at mine below. It adds more than half of the time of the fastest solution, but the code is three times shorter.
  • If you want a one-liner and do not mind using an external library, go for github.com/dustin/go-humanize. It is more than twice slower as the fastest solution, but the library might help you with other formatting.
  • If you want localized output, choose golang.org/x/text/message. It is seven times slower than the fastest solution, but the luxury of matching the consumer's language does not come free.

Other hand-coded solutions are fast too and you will not regret choosing any of them, except for the usage of regexp. Using regexp needs the shortest code snippet, but the performance is so tragic, that it is not worth it.

My contribution to this topic, which you can try running in the playground:

func formatInt(number int) string {
	output := strconv.Itoa(number)
	startOffset := 3
	if number &lt; 0 {
		startOffset++
	}
	for outputIndex := len(output); outputIndex &gt; startOffset; {
		outputIndex -= 3
		output = output[:outputIndex] + &quot;,&quot; + output[outputIndex:]
	}
	return output
}

答案9

得分: 3

这绝对不是基准测试的领导者,但如果代码清晰且性能不关键,谁在乎呢?

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))
}

而这是用于基准测试的代码:实现与icza的非常相似

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 // 预先在堆栈上分配缓冲区,而不是使用make([]byte,n)
        buf := sbuf[0:l_buf]
        // 从末尾复制str
        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--
                // 每3个字符插入一个逗号
                c3++
                if c3 == 3 && (s_i > 0 || num>0)  {
                        buf[b_i] = ','
            			b_i--
                        c3 = 0
                }
	}
}

对于输入-1234567890123456789,它比icza的快大约15%。

英文:

This is definitely not a leader of the benchmarks but who cares if code is clear and the performance is not critical?

package main
import (
	&quot;fmt&quot;
)

func IntComma(i int) string {
	if (i &lt; 0) {
		return &quot;-&quot; + IntComma(-i)
	}
	if (i &lt; 1000) {
		return fmt.Sprintf(&quot;%d&quot;,i)
	}
	return IntComma(i / 1000) + &quot;,&quot; + fmt.Sprintf(&quot;%03d&quot;,i % 1000)
}

func main() {
	fmt.Println(IntComma(1234567891234567))
}

And this is for the benchmarks: implementation is very similar to that of icza

func IntCommaB(num int) string {
        str := strconv.Itoa(num)
        l_str := len(str)
        digits := l_str
        if num &lt; 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 &amp;&amp; (s_i &gt; 0 || num&gt;0)  {
                        buf[b_i] = &#39;,&#39;
            			b_i--
                        c3 = 0
                }
	}
}

With input -1234567890123456789 it is about 15% faster than icza's

答案10

得分: 2

使用https://github.com/dustin/go-humanize .. 它有很多辅助函数来处理这些事情。除了以字节为单位的MiB、MB和其他好东西。

英文:

Use https://github.com/dustin/go-humanize .. it has a bunch of helpers to deal with those things. In addition to bytes as MiB, MB, and other goodies.

答案11

得分: 0

The package humanize can do the magic! Refer the documentation of this package here. To use this package, install it first by using a tool like Git SCM. If you are using Git Bash, open the shell window and type:

go get -u github.com/dustin/go-humanize

Once this is done, you can use the following solution code (Say, main.go):

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)));
}

There are other variations to Commaf like BigComma, Comma, BigCommaf etc. which depends on the data type of your input.

So, on running this program using the command:

go run main.go

You will see an output such as this:

123,456,789
-1,000,000,000
-100,000.005
100,000
英文:

The package humanize can do the magic! Refer the documentation of this package here. To use this package, install it first by using a tool like Git SCM. If you are using Git Bash, open the shell window and type:

go get -u github.com/dustin/go-humanize

Once this is done, you can use the following solution code (Say, main.go):

package main

import (
    &quot;fmt&quot;
    &quot;github.com/dustin/go-humanize&quot;
)

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)));
}

There are other variations to Commaf like BigComma, Comma, BigCommaf etc. which depends on the data type of your input.

So, on running this program using the command:

go run main.go

You will see an output such as this:

123,456,789
-1,000,000,000
-100,000.005
100,000

答案12

得分: 0

你也可以使用这个小包:https://github.com/floscodes/golang-thousands。

只需将你的数字转换为字符串,然后像这样使用Separate函数:

n := "3478686" // 你的数字作为字符串

thousands.Separate(n, "en") // 添加千位分隔符。第二个参数设置语言模式。
英文:

You can also use this small package: https://github.com/floscodes/golang-thousands.

Just convert your number to a string an then use the Separate-function like this:

n:=&quot;3478686&quot; // your number as a string

thousands.Separate(n, &quot;en&quot;) // adds thousands separators. the second argument sets the language mode.

答案13

得分: -2

如果您不想使用库(无论出于什么原因),我写了这个代码。它似乎可以工作,并且可以使用任何指定的符号作为分隔符:

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发布的解决方案,并欢迎任何可以使我的代码完美工作的修改。

英文:

If you don't want to use a library (for whatever reason), I knocked this up. It seems to work and can use any specified rune as a delimiter:

import (
    &quot;strconv&quot;
)

func delimitNumeral(i int, delim rune) string {

    src := strconv.Itoa(i)
    strLen := utf8.RuneCountInString(src)
    outStr := &quot;&quot;
    digitCount := 0
    for i := strLen - 1; i &gt;= 0; i-- {

	    outStr = src[i:i+1] + outStr
	    if digitCount == 2 {
	    	outStr = string(delim) + outStr
		    digitCount = 0
	    } else {
	        digitCount++
        }
    }

    return outStr
}

Note: after further testing, this function doesn't work perfectly. I would suggest using the solution posted by @IvanTung, and welcome any edits from anyone who can get mine to work perfectly.

答案14

得分: -3

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:]) + "." + parts1
}
return commas(parts[0]) + "." + parts1
}

英文:
import (&quot;fmt&quot;; &quot;strings&quot;)

func commas(s string) string {
    if len(s) &lt;= 3 {
        return s
    } else {
        return commas(s[0:len(s)-3]) + &quot;,&quot; + s[len(s)-3:]
    }
}

func toString(f float64) string {
    parts := strings.Split(fmt.Sprintf(&quot;%.2f&quot;, f), &quot;.&quot;)
	if parts[0][0] == &#39;-&#39; {
    	return &quot;-&quot; + commas(parts[0][1:]) + &quot;.&quot; + parts[1]
	}
    return commas(parts[0]) + &quot;.&quot; + parts[1]
}

huangapple
  • 本文由 发表于 2012年10月23日 05:38:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/13020308.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定