精度问题
设置是物理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而不会丢失精度(使用上面的函数)
答案 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
虽然这种技巧适用于这种情况,但并不能保证在所有情况下都能正常工作。真正的解决方案是让制造商聘请一些称职的数学家。我想知道他们的软件和硬件还有其他什么错误。