golang十进制到十六进制转换错误

时间:2014-11-29 02:58:11

标签: go printf hex decimal

精度问题

设置是物理i按钮(1线规格),按制造商印刷的十六进制值(可信值)。 IoT设备将二进制编码为decminal - Golang将接收的值返回给Hex。

收到的十进制值是:

var V = 10736581604118680000
fmt.Sprintf("%016X", m.V)[2:14]) // adds uppercase and truncation of output

提供000015877CD1

预期的可信输出为000015877CD0

钥匙上的雕刻十六进制为95 000015877CD0 01

http://www.rapidtables.com/convert/number/decimal-to-hex.htm(被信任?)表示使用的golang函数丢失了精度。编码为19位十进制数字的二进制值可以通过Golang转换为Hex而不会丢失精度(使用上面的函数)

1 个答案:

答案 0 :(得分:2)

例如,

package main

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

func hexdec(s string) uint64 {
    d := uint64(0)
    for i := 0; i < len(s); i++ {
        x := uint64(s[i])
        if x >= 'a' {
            x -= 'a' - 'A'
        }
        d1 := x - '0'
        if d1 > 9 {
            d1 = 10 + d1 - ('A' - '0')
        }
        if 0 > d1 || d1 > 15 {
            panic("hexdec")
        }
        d = (16 * d) + d1
    }
    return d
}

func main() {
    x := "95000015877CD001"
    fmt.Println(x)
    n, err := strconv.ParseUint(x, 16, 64)
    fmt.Println(n, err)
    s := fmt.Sprintf("%016X", n)[2:14]
    fmt.Println(s)
    z, t := big.NewInt(0).SetString(x, 16)
    fmt.Println(z, t)
    s = fmt.Sprintf("%016X", z)[2:14]
    fmt.Println(s)
    fmt.Println(hexdec(x))
}

输出:

95000015877CD001
10736581604118679553 <nil>
000015877CD0
10736581604118679553 true
000015877CD0
10736581604118679553

请注意,您接近64位整数的限制:

uint64  the set of all unsigned 64-bit integers (0 to 18446744073709551615)

在哪里
Var V = 10736581604118680000

来自?


数字10736581604118680000是整数10736581604118679553的浮点近似值(1.073658160411868e + 19)。制造商可能不理解浮点数:What Every Computer Scientist Should Know About Floating-Point Arithmetic。给定整数10736581604118680000,Go计算正确的结果。 Go在数学上是正确的。

所以让我们试着告诉Go 10736581604118680000不是一个精确的整数,它是一个近似的浮点数。

例如,

package main

import (
    "fmt"
    "strconv"
)

func main() {
    d := "10736581604118680000"
    f, err := strconv.ParseFloat(d, 64)
    fmt.Println(f, err)
    z := uint64(f)
    fmt.Println(z)
    s := fmt.Sprintf("%016X", z)[2:14]
    fmt.Println(s)
}

输出:

1.073658160411868e+19 <nil>
10736581604118679552
000015877CD0

虽然这种技巧适用于这种情况,但并不能保证在所有情况下都能正常工作。真正的解决方案是让制造商聘请一些称职的数学家。我想知道他们的软件和硬件还有其他什么错误。