首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将int转换为十六进制字符串的有效方法,然后在Golang中用0来填充它?

将int转换为十六进制字符串的有效方法,然后在Golang中用0来填充它?
EN

Stack Overflow用户
提问于 2017-10-21 07:06:55
回答 3查看 2.7K关注 0票数 2

我试着把1000万的int转换成十六进制,然后用0填充它,以便得到一个表示十六进制数的4个字符字符串。

到目前为止,我尝试了以下几点:

代码语言:javascript
复制
var hexNumber string
for idx := O; idx < 10000000; idx++ {
    hexNumber = fmt.Sprintf("%04x", idx)

    // Do some stuff ....
}

但是fmt.Sprintf并不是很有效率。我怎样才能有效地做到这一点呢?

解决方案:--事实证明@peterSO strconv.AppendInt解决方案要快得多。

代码语言:javascript
复制
package bench

import (
    "fmt"
    "strconv"
    "strings"
    "testing"
)

var stringHex [16]string
var runesHex [16]rune

func init() {
    stringHex = [16]string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
    runesHex = [16]rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}
}

func intToHex1(intNumber int) string {
    hexNumber := []rune("0000")
    for i, j := int(0), uint(12); i < 4; i, j = i+1, j-4 {
        hexNumber[i] = runesHex[(intNumber>>j)&0x0f]
    }
    return string(hexNumber)
}

func intToHex2(intNumber int) string {
    hexNumber := "0000"
    for i, j := int(0), uint(12); i < 4; i, j = i+1, j-4 {
        hexNumber = hexNumber[:i] + stringHex[(intNumber>>j)&0x0f] + hexNumber[i+1:]
    }
    return hexNumber
}

func BenchmarkFmtSprintf(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        hexNumber := fmt.Sprintf("%04x", n)
        _ = hexNumber
    }
}

func BenchmarkStrconvFormatInt(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        retStr := strings.Repeat("0", 4) + strconv.FormatInt(int64(n), 16)
        hexNumber := retStr[(len(retStr) - 4):]
        _ = hexNumber
    }
}

func BenchmarkAppend(b *testing.B) {
    b.ReportAllocs()
    buf := []byte{'0', '0', '0', '0', 4 + 16: 0}
    for n := 0; n < b.N; n++ {
        buf = strconv.AppendInt(buf[:4], int64(n), 16)
        hexNumber := string(buf[len(buf)-4:])
        _ = hexNumber
    }
}

func BenchmarkIntToHex1(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        hexNumber := intToHex1(n)
        _ = hexNumber
    }
}

func BenchmarkIntToHex2(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        hexNumber := intToHex2(n)
        _ = hexNumber
    }
}

所以基准是:

代码语言:javascript
复制
BenchmarkFmtSprintf-2            3000000               364 ns/op              16 B/op          2 allocs/op
BenchmarkStrconvFormatInt-2      5000000               354 ns/op              15 B/op          3 allocs/op
BenchmarkAppend-2               20000000                75.6 ns/op             0 B/op          0 allocs/op
BenchmarkIntToHex1-2            10000000               162 ns/op               8 B/op          1 allocs/op
BenchmarkIntToHex2-2             3000000               536 ns/op              16 B/op          4 allocs/op
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-21 09:09:50

strconv.AppendUint似乎比fmt.Sprintf快。例如,

hex_test.go

代码语言:javascript
复制
package main

import (
    "fmt"
    "strconv"
    "testing"
)

func BenchmarkFmtSprintf(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        hexNumber := fmt.Sprintf("%04x", n&0xFFFF)
        _ = hexNumber
    }
}

func BenchmarkAppend(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        buf := []byte{'0', '0', '0', 3 + 4: 0}
        buf = strconv.AppendUint(buf[:3], uint64(n)&0xFFFF, 16)
        hexNumber := string(buf[len(buf)-4:])
        _ = hexNumber // Do some stuff ....
    }
}

输出:

代码语言:javascript
复制
$ go test -bench=. hex_test.go
BenchmarkSprintf-4      10000000       116 ns/op      16 B/op     1 allocs/op
BenchmarkAppend-4       100000000       19.2 ns/op     0 B/op     0 allocs/op
票数 2
EN

Stack Overflow用户

发布于 2022-05-17 06:51:43

我不确定这是否是最好的方法,但我有要点游乐场演示了您正在试图解决的问题,以及我最终采取的方法。

代码语言:javascript
复制
// hex formater with %x can lose a leading 0
// This can produce strings with an odd number of hex digits

package main

import (
    "encoding/binary"
    "encoding/hex"
    "fmt"
)

func main() {
    var foo uint16 = 0x0ABC // decimal 2748

    with_pct := fmt.Sprintf("%x", foo)
    fmt.Printf("With string formatter: %q\n", with_pct)
    // Outputs: With string formatter: "abc"

    // I hope there is a cleaner way to get an integer into a []byte
    foo_bytes := make([]byte, 2)
    binary.BigEndian.PutUint16(foo_bytes, foo)

    with_bytes := hex.EncodeToString(foo_bytes)
    fmt.Printf("With hex encoding: %q\n", with_bytes)
    // Outputs: With hex encoding: "0abc"
}

我对这种做法并不特别满意。我必须根据int的大小手动设置字节数组的长度,因为Go的len()函数不像C的size_of操作符。

当试图获得非负big.Int的十六进制表示时,这确实更好地工作,因为.Bytes()给出了大端字节数组。

票数 0
EN

Stack Overflow用户

发布于 2017-10-21 07:56:47

您应该能够使用strconv,然后只需手动衬垫。这可能就不那么管用了。

代码语言:javascript
复制
strconv.FormatInt(idx,16)
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46860905

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档