For example,
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))
}
Output:
95000015877CD001
10736581604118679553 <nil>
000015877CD0
10736581604118679553 true
000015877CD0
10736581604118679553
Note that you are near the limits of 64-bit integers:
uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615)
Where does
Var V = 10736581604118680000
come from?
The number 10736581604118680000 is a floating-point approximation (1.073658160411868e+19) of the integer 10736581604118679553. The manufacturer probably doesn't understand floating-point: What Every Computer Scientist Should Know About Floating-Point Arithmetic. Given the integer 10736581604118680000, Go calculates the correct result. Go is mathematically correct.
So let's try telling Go that 10736581604118680000 is not an exact integer, that it's an approximate floating-point number.
For example,
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)
}
Output:
1.073658160411868e+19 <nil>
10736581604118679552
000015877CD0
While this trick works in this case, it's not guaranteed to work in all cases. The real solution is for the manufacturer to employ some competent mathematicians. I wonder what other bugs there are in their software and hardware.