为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
守着星空守着你 2021-09-09 13:53:43
精度问题设置是一个物理 i 按钮(1 线规范),带有制造商印刷的十六进制值(可信值)。物联网设备将二进制编码为十进制 - Golang 将接收到的值返回为十六进制。接收到的十进制值为:var V = 10736581604118680000fmt.Sprintf("%016X", m.V)[2:14]) // adds uppercase and truncation of output提供 000015877CD1预期的可信输出是 000015877CD0钥匙上刻有的十六进制是 95 000015877CD0 01http://www.rapidtables.com/convert/number/decimal-to-hex.htm(可信?)表示使用的golang函数丢失了精度。编码为 19 位十进制数字的二进制值可以被 Golang 转换为十六进制而不会损失精度(使用上面的函数)
查看完整描述

1 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

例如,


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)。制造商可能不了解浮点:每个计算机科学家应该知道什么。给定整数 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

虽然这个技巧在这种情况下有效,但不能保证在所有情况下都有效。真正的解决方案是制造商聘请一些有能力的数学家。我想知道他们的软件和硬件中还有哪些其他错误。


查看完整回答
反对 回复 2021-09-09
  • 1 回答
  • 0 关注
  • 189 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信