Go Varint返回预期值的一半
为什么此代码的输出是:Go Varint返回预期值的一半,go,Go,为什么此代码的输出是: package main import ( "fmt" "encoding/binary" ) func main() { var myByte byte = 18 array := []byte{myByte} val, n := binary.Varint(array) fmt.Printf("value: %d, num bytes: %d\n", val, n) } value:9,num bytes:1而不是
package main
import (
"fmt"
"encoding/binary"
)
func main() {
var myByte byte = 18
array := []byte{myByte}
val, n := binary.Varint(array)
fmt.Printf("value: %d, num bytes: %d\n", val, n)
}
value:9,num bytes:1
而不是value:18,num bytes:1
它可能与2的补码有关,但我不知道怎么做。是的。检查此修改版本:
你可以看到消极和积极之间的“之字形”。这是因为,根据,变量使用“之字形”编码,因此小绝对值的值用小值编码。TLDR:使用
Uvarint
方法正确解码无符号字节。。这就是默认情况下的字节
该字节是无符号存储的(因为默认情况下字节是无符号的-在大多数语言中,它是uint8
的别名)
当您解码该号码时,您正在调用binary.Varint
。。它解码一个有符号的数字。由于符号位的原因,这会导致数字不正确
使用binary.Uvarint
。。也就是说,对一个无符号数字进行解码,您将得到正确的结果:
val, n := binary.Uvarint(array) // val = 18, n = 1
扩展示例:
让我们看看你的数字-18。在二进制中,它是这样的:
00010010
binary.Varint
函数如下所示:
func Varint(buf []byte) (int64, int) {
ux, n := Uvarint(buf) // ok to continue in presence of error
x := int64(ux >> 1)
if ux&1 != 0 {
x = ^x
}
return x, n
}
基本上,它将首先获取您提供的未签名值:18
然后,它会将所有字节移位1。这导致:
00001001
这是9
的二进制表示形式。请注意,符号位仍然是0-这表示一个正数。然后,它检查是否通过按位并将原始值(18
)与1
相加来反转结果。它这样做是因为,它是在“我知道这个数字是有符号的”上下文中运行的-这就是函数存在的原因:
00010010
00000001
--------
00000000
= 0
在这一点上,零等于零——因此该方法返回x
——即9
让我们试试1
使用1作为输入:
00000001
右移:
00000000
原始编号(1)加上1:
此时,结果不等于零。。结果是相反的:
11111111
这是-1
的有符号表示(注意符号位现在是1..表示负数)。好的,那么为什么2产生1,1产生-1?好的,但是为什么我输入的18产生9?18 = 00010010
00000000
00000001
00000001
--------
= 1
11111111