How to write LEB128 in Go

huangapple go评论87阅读模式
英文:

How to write LEB128 in Go

问题

如何在Go中将整数写入LEB128格式?我正在尝试将int32编码为Minecraft VarInt,到目前为止,我已经尝试将维基百科上的示例导入到Go中。但是在测试时,我得到了错误的结果,维基百科上说-1应该等于[255 255 255 255 15],但我得到的是[255 255 255 255 255]。我在这里做错了什么?

func WriteVarInt2(v int32) []byte{
   var out []byte
   c := 0
   for{
       currentByte := byte(v & 0b01111111)
       v >>= 7
       if v != 0 {
           currentByte |= 0b10000000
       }
       out = append(out, currentByte)
       c++

       if c >= 5 || v == 0{
           return out
       }
    }
}
英文:

How do you write an integer to LEB128 format in Go? I'm trying to encode an int32 to a Minecraft VarInt, so far I've tried importing the example on the wiki to Go. I get the wrong results when testing though, wiki says -1 should equal [255 255 255 255 15], but I get [255 255 255 255 255] instead. What I'm I doing wrong here?

func WriteVarInt2(v int32) []byte{
   var out []byte
   c := 0
   for{
	   currentByte := byte(v & 0b01111111)
  	   v >>= 7
	   if v != 0 {
		   currentByte |= 0b10000000
	   }
	   out = append(out, currentByte)
	   c++

	   if c >= 5 || v == 0{
		   return out
	   }
    }
}

答案1

得分: 6

问题出在移位操作上。

>>算术右移>>>逻辑右移。它们的区别在于 >> 会带入符号位(在左边),而 >>> 会带入零(无论符号位是什么)。

LEB128 变长整数的算法使用的是逻辑右移,而 Go 的 >> 是算术右移。

在 Go 中没有明确的逻辑右移操作,但是如果将数字视为无符号数,你将得到逻辑右移的效果:

func WriteVarInt2(v_ int32) []byte {
    v := uint32(v_)

    // 函数的其余部分保持不变
    // ...
}

进行测试:

fmt.Println(WriteVarInt2(-1))

输出结果如预期(在 Go Playground 上尝试):

[255 255 255 255 15]
英文:

The problem is with the shifting operation.

>> is arithmetic shift right, >>> is logical shift right. The difference is that >> brings in the sign bit (on the left), while >>> brings in zeros (whatever the sign bit was).

The algorithm of LEB128's Varint uses logical shift, and Go's >> is arithmetic shift.

There is no distinct logical shift in Go, but if you treat the number as unsigned, you'll get exactly that:

func WriteVarInt2(v_ int32) []byte {
	v := uint32(v_)

    // rest of your function unchanged
    // ...
}

Testing it:

fmt.Println(WriteVarInt2(-1))

Output is as expected (try it on the Go Playground):

[255 255 255 255 15]

huangapple
  • 本文由 发表于 2021年6月26日 06:01:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/68137460.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定