英文:
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]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论