How to write LEB128 in Go

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

How to write LEB128 in Go

问题

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

  1. func WriteVarInt2(v int32) []byte{
  2. var out []byte
  3. c := 0
  4. for{
  5. currentByte := byte(v & 0b01111111)
  6. v >>= 7
  7. if v != 0 {
  8. currentByte |= 0b10000000
  9. }
  10. out = append(out, currentByte)
  11. c++
  12. if c >= 5 || v == 0{
  13. return out
  14. }
  15. }
  16. }
英文:

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?

  1. func WriteVarInt2(v int32) []byte{
  2. var out []byte
  3. c := 0
  4. for{
  5. currentByte := byte(v & 0b01111111)
  6. v >>= 7
  7. if v != 0 {
  8. currentByte |= 0b10000000
  9. }
  10. out = append(out, currentByte)
  11. c++
  12. if c >= 5 || v == 0{
  13. return out
  14. }
  15. }
  16. }

答案1

得分: 6

问题出在移位操作上。

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

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

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

  1. func WriteVarInt2(v_ int32) []byte {
  2. v := uint32(v_)
  3. // 函数的其余部分保持不变
  4. // ...
  5. }

进行测试:

  1. fmt.Println(WriteVarInt2(-1))

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

  1. [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:

  1. func WriteVarInt2(v_ int32) []byte {
  2. v := uint32(v_)
  3. // rest of your function unchanged
  4. // ...
  5. }

Testing it:

  1. fmt.Println(WriteVarInt2(-1))

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

  1. [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:

确定