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

Go Varint 返回一半的预期值

Go Varint 返回一半的预期值

Go
幕布斯7119047 2021-09-13 09:47:51
为什么这段代码的输出是:package mainimport (    "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 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

使用该Uvarint方法正确解码无符号字节 .. 这是byte默认情况下的 a 。


字节以无符号形式存储(因为默认情况下字节是无符号的 -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

AND原始数字 (1)与 1:


00000001

00000001

--------

     = 1

此时,结果不等于零..所以结果反转:


11111111

这是-1(注意符号位现在是 1 .. 表示负数)的有符号表示。


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

添加回答

举报

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