2

我想将 a 转换big.Int为简单的 base32。不是由zBase32或Crockford实现的RFC 4648类的标准 base32 东西,我只想要每个字符 0-9A-V 字符集的简单普通 5 位。base32

我知道这个base32包,它没有做我想要的 - 它以标准的 32 为基数构建结果,并带有填充和我不想要的东西。当然,我可以使用它并撕下尾随的“=”字符并破解剩余的内容,但这似乎是一个残酷的解决方案。

有一个big.SetString(string, base)可以解析字符串形式的 base32 数字,但没有反向 - 这就是我真正想要的,big.GetString(base)就像 Java 一样BigInteger.toString(int base)

然而,有一个nat.string正是想要的。我怎样才能访问它?

有没有一种方法可以手动扩展big以实现正确的big.GetString(base)调用?nat.stringcharset

有没有办法可以接触到未导出big.natbig使用和调用nat.string

还有什么我可以做的吗?

PS我也有兴趣使用nat.trailingZeroBits- 我不得不自己写,因为我没有意识到这已经完成了。

4

3 回答 3

2

您根本无法访问未导出的函数。您需要重新编写至少一部分nat.go才能实现该功能。其中一些功能看起来非常有用,因此可能值得向小组发送功能请求,golang-nuts要求在未来的版本中导出其中的一些功能。

但是,您可以使用它strconv.FormatInt()来执行您需要的操作。

给定一个big.Int b你可以做的:

strconv.FormatInt(b.Int64(), 32)

完整示例:

package main

import (
    "fmt"
    "math/big"
    "strconv"
)

func main() {
    i := 3286583923486565782 // Some random integer
    b := big.NewInt(int64(i))
    fmt.Println(strconv.FormatInt(b.Int64(), 32))
}

产生:

2r72al99uq9cm

操场

于 2013-10-07T02:47:16.023 回答
2

我认为 go 团队永远不会导出任何内容,nat因为这是big.Int. ToBase他们可能会善意地接受从 导出函数的请求big.Int

同时,这里有一个经过轻微测试的朴素基础转换器,适合您

func ToBase(x *big.Int, base int) string {
    if x.Sign() == 0 {
        return "0"
    }
    y := new(big.Int).Set(x)
    b := big.NewInt(int64(base))
    charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    out := make([]byte, 0, 16)
    negative := false
    if y.Sign() < 0 {
        negative = true
        y.Neg(y)
    }
    digit := new(big.Int)
    for y.Sign() != 0 {
        y.DivMod(y, b, digit)
        out = append(out, charset[digit.Int64()])
    }
    if negative {
        out = append(out, '-')
    }
    // Reverse out
    for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
        out[i], out[j] = out[j], out[i]
    }
    return string(out)
}

游乐场链接

于 2013-10-07T16:15:33.393 回答
1

我已经在 go-nuts 线程上发布了。他们似乎对我的建议很满意。

同时 - 我的 Base32 实现(不处理类似符号nat

// The digits
const charset string = "0123456789ABCDEFGHIJKLMNOPQRSTUV"

/*
 Convert the big to base32
*/
func Base32(n big.Int) string {
    // The bytes of the number
    bytes := n.Bytes()
    nBytes := len(bytes)
    if nBytes == 0 {
        // Special case 0.
        return "0"
    }
    // How many digits will be in the string?
    nBits := nBytes * 8
    nDigits := nBits / 5
    if nBits%5 > 0 {
        nDigits += 1
    }
    // Grow the digits into an array
    digits := make([]byte, nDigits)
    digit := nDigits - 1
    // Peel off 5 bits from the array each time.
    for b, shr := nBytes-1, uint(0); b >= 0; {
        // The next lot is there.
        shrp5 := shr + 5
        // Build my bits.
        x := (bytes[b] >> shr)
        if shrp5 > 8 && b > 0 {
            of := shrp5 - 8
            // Add in some bits from the next byte too.
            x &= (1 << (8 - shr)) - 1
            x |= bytes[b-1] << (5 - of)
        }
        // Shift 5 more.
        shr = shrp5
        // Should we step to next byte?
        if shr >= 8 {
            // Next byte
            shr -= 8
            b -= 1
        }
        x &= 0x1f
        // Build my digit
        digits[digit] = charset[x]
        digit -= 1
    }
    // Skip leading zeros.
    lz := 0
    for digits[lz] == '0' {
        lz += 1
    }
    // Return the string equivalent.
    return string(digits[lz:])
}

欢迎评论。

于 2013-10-08T23:13:57.023 回答