打印时如何用零填充数字?

我如何打印一个数字或使一个字符串与零填充使其固定宽度?

例如,如果我有数字 12,我想使它 000012

149629 次浏览

Fmt 包可以为您做到这一点:

fmt.Printf("|%06d|%6d|\n", 12, 345)

产出:

|000012|   345|

注意% 06d 中的0,这将使它的宽度为6,并用0填充它。第二个将填充空格。

你自己试试看: http://play.golang.org/p/cinDspMccp

列表打印格式在去郎”这个问题提醒我们,还有一面旗帜:

-垫,空格在右边而不是左边(字段左对齐)


如果您想用其他字符串序列(比‘ 0’或‘ ’更复杂)填充,您可以看到更多使用 DaddyOh/golang-samples/pad.go填充的示例:

  • leftPad(s string, padStr string, pLen int)
  • rightPad(s string, padStr string, pLen int)
  • leftPad2Len(s string, padStr string, overallLen int)
  • rightPad2Len(s string, padStr string, overallLen int)

< kbd > play.golang.org :

1234567890


leftPad(str, "*", 3)  ***1234567890
leftPad2Len(str, "*-", 13)  -*-1234567890
leftPad2Len(str, "*-", 14)  *-*-1234567890
leftPad2Len(str, "*", 14)  ****1234567890
leftPad2Len(str, "*-x", 14)  x*-x1234567890
leftPad2Len(str, "ABCDE", 14)  BCDE1234567890
leftPad2Len(str, "ABCDE", 4)  7890
rightPad(str, "*", 3)  1234567890***
rightPad(str, "*!", 3)  1234567890*!*!*!
rightPad2Len(str, "*-", 13)  1234567890*-*
rightPad2Len(str, "*-", 14)  1234567890*-*-
rightPad2Len(str, "*", 14)  1234567890****
rightPad2Len(str, "*-x", 14)  1234567890*-x*
rightPad2Len(str, "ABCDE", 14)  1234567890ABCD
rightPad2Len(str, "ABCDE", 4)  1234
func lpad(s string,pad string, plength int)string{
for i:=len(s);i<plength;i++{
s=pad+s
}
return s
}

Lpad (“3”,“0”,2)结果: “03”

Lpad (“12”,“0”,6)结果: “000012”

有一个最简单的方法可以达到这个目的

func padNumberWithZero(value uint32) string {
return fmt.Sprintf("%02d", value)
}

fmt.Sprintf格式化并返回一个字符串,而不需要在任何地方打印它。 这里 %02d表示左边的垫零,表示小于2位数的值。如果给定的值有2个或更多的数字,它将不会垫。例如:

  • 如果输入为1,则输出为01。
  • 如果输入为12,则输出为12。
  • 如果输入为1992,则输出为1992。

可以使用 %03d或更多来填充更多的零。

使用 Fmt 软件包中的 Printf函数,width6,填充字符为 0:

import "fmt"
fmt.Printf("%06d", 12) // Prints to stdout '000012'

设置 宽度的方法是在格式说明符(‘动词’)前面直接放置一个整数:

fmt.Printf("%d", 12)   // Uses default width,                          prints '12'
fmt.Printf("%6d", 12)  // Uses a width of 6 and left pads with spaces, prints '    12'

Golang (和大多数其他语言)支持的唯一 填充字符是空格和 0:

fmt.Printf("%6d", 12)   // Default padding is spaces, prints '    12'
fmt.Printf("%06d", 12)  // Change to 0 padding,       prints '000012'

可以通过预先设置一个负的 -来进行 正当理由打印:

fmt.Printf("%-6d", 12)   // Padding right-justified, prints '12    '

注意,对于 浮点数浮点数,宽度包括整个格式字符串:

fmt.Printf("%06.1f", 12.0) // Prints '0012.0' (width is 6, precision is 1 digit)

值得注意的是,宽度也可以通过使用 *代替数字,并将宽度作为 int参数传递,以编程方式进行设置:

myWidth := 6
fmt.Printf("%0*d", myWidth, 12) // Prints '000012' as before

例如,如果您想打印的最大值只在运行时知道(在下面的示例中称为 maxVal) ,那么这可能很有用:

myWidth := 1 + int(math.Log10(float64(maxVal)))
fmt.Printf("%*d", myWidth, nextVal)

最后,如果你不想打印到 stdout但是返回一个字符串,使用 Fmt 软件包中的 Sprintf和相同的参数:

s := fmt.Sprintf("%06d", 12) // returns '000012' as a String

对于那些想要右移的人,你可以这样做:

str2pad := "12"
padWith := "0"
amt2pad := 6


//This will make sure there is always 6 characters total, padded on the right side
//Note to check if strings.Repeat returns a negative value
paddedStr := str2pad + strings.Repeat(padWith, amt2pad - len(str2pad))


//Outputs 120000

以防万一,如果您想要通过连接形成另一个单词的前缀或后缀,您可以使用下面的代码。

package main


import "fmt"


func main() {
concatenatedWord:= "COUNTER_"+fmt.Sprintf("%02d", 1)
// use concatenatedWord
fmt.Println("ConcatenatedWordword is", concatenatedWord)
}

输出: ConcatenatedWordword 是 COUNTER _ 01

连结: https://play.golang.org/p/25g3L8TXiPP

另一个选择是 golang.org/x/text/number套餐:

package main


import (
"golang.org/x/text/language"
"golang.org/x/text/message"
"golang.org/x/text/number"
)


var fmt = message.NewPrinter(language.English)


func main() {
n := number.Decimal(
12, number.Pad('0'), number.FormatWidth(6),
)
fmt.Println(n) // 000012
}

Https://pkg.go.dev/golang.org/x/text/number

数学方法:


func padLeft(v int64, length int) string {
abs := math.Abs(float64(v))
var padding int
if v != 0 {
min := math.Pow10(length - 1)
if min-abs > 0 {
l := math.Log10(abs)
if l == float64(int64(l)) {
l++
}
padding = length - int(math.Ceil(l))
}
} else {
padding = length - 1
}
builder := strings.Builder{}
if v < 0 {
length = length + 1
}
builder.Grow(length * 4)
if v < 0 {
builder.WriteRune('-')
}
for i := 0; i < padding; i++ {
builder.WriteRune('0')
}
builder.WriteString(strconv.FormatInt(int64(abs), 10))
return builder.String()
}


例如:

package main


import (
"fmt"
"math"
"strconv"
"strings"
)


func main() {
v := padLeft(0, 10)
fmt.Println(v, "length:", len(v), "expected (10)")
// 0000000000 length: 10 expected (10)


v = padLeft(5, 10)
fmt.Println(v, "length:", len(v), "expected (10)")
// 0000000005 length: 10 expected (10)


v = padLeft(12345, 10)
fmt.Println(v, "length:", len(v), "expected (10)")
// 0000012345 length: 10 expected (10)


v = padLeft(333, 6)
fmt.Println(v, "length:", len(v), "expected (6)")
// 000333 length: 6 expected (6)


v = padLeft(1, 10)
fmt.Println(v, "length:", len(v), "expected (10)")
// 0000000001 length: 10 expected (10)


v = padLeft(12345, 4)
fmt.Println(v, "length:", len(v), "expected (5)")
// 12345 length: 5 expected (5)


v = padLeft(3, 4)
fmt.Println(v, "length:", len(v), "expected (4)")
// 0003 length: 4 expected (4)


v = padLeft(-3, 4)
fmt.Println(v, "length:", len(v), "expected (5)")
// -0003 length: 5 expected (5)


}


func padLeft(v int64, length int) string {
abs := math.Abs(float64(v))
var padding int
if v != 0 {
min := math.Pow10(length - 1)


if min-abs > 0 {
l := math.Log10(abs)
if l == float64(int64(l)) {
l++
}
padding = length - int(math.Ceil(l))
}
} else {
padding = length -1
}
builder := strings.Builder{}
if v < 0 {
length = length + 1
}
builder.Grow(length * 4)
if v < 0 {
builder.WriteRune('-')
}
for i := 0; i < padding; i++ {
builder.WriteRune('0')
}
builder.WriteString(strconv.FormatInt(int64(abs), 10))
return builder.String()
}


游乐场连结

Https://play.golang.org/p/1gfutmuqdlm

基准

使用稍作修改的版本,因为我的价值观总是正的:


// Random is basically just a rand.Rand in this case


func (r Random) codeWithFmt(length int) string {
max := int64(math.Pow10(length)) - 1
var v int64
for v == 0 {
v = r.Int63n(max)
}
return fmt.Sprintf("%0*d", length, v)
}


func (r Random) Code(digits int) string {
max := int64(math.Pow10(digits)) - 1
var v int64
for v == 0 {
v = r.Int63n(max)
}
var padding int
if math.Pow10(digits-1)-float64(v) > 0 {
lv := math.Log10(float64(v))
if lv == float64(int64(lv)) {
lv++
}
padding = digits - int(math.Ceil(lv))
}
builder := strings.Builder{}
builder.Grow(digits * 4)
for i := 0; i < padding; i++ {
builder.WriteRune('0')
}
builder.WriteString(strconv.FormatInt(v, 10))
return builder.String()
}



func BenchmarkCodeGeneration(b *testing.B) {
assert := require.New(b)
_ = assert
r := New()
for i := 0; i < b.N; i++ {
// assert.Len(r.Code(7), 7)
r.Code(7)
}
}


func BenchmarkCodeGenerationWithFmt(b *testing.B) {
assert := require.New(b)
_ = assert
r := New()
for i := 0; i < b.N; i++ {
// assert.Len(r.codeWithFmt(7), 7)
r.codeWithFmt(7)
}
}

基准业绩

BenchmarkCodeGeneration
BenchmarkCodeGeneration-8            5219466           204.8 ns/op        56 B/op          3 allocs/op
BenchmarkCodeGenerationWithFmt
BenchmarkCodeGenerationWithFmt-8     4306922           283.9 ns/op        32 B/op          4 allocs/op

我的解决办法是:

func leftZeroPad(number, padWidth int64) string {
return fmt.Sprintf(fmt.Sprintf("%%0%dd", padWidth), number)
}

示例用法:

fmt.Printf("%v", leftZeroPad(12, 10))

印刷品:

0000000012

这样做的好处是,如果需要,您可以在运行时指定垫长度。