在gpb proto2(https://developers.google.com/protocol-buffers/docs/proto#scalar)的标量类型描述中,它说:
INT32
使用可变长度编码。编码负面效率低下 数字 - 如果您的字段可能具有负值,请使用sint32 代替。
SINT32
使用可变长度编码。签名的int值。这些更多 有效地编码负数而不是常规的int32。
对于正值,sint32是否与int32一样有效?
换句话说,有没有理由使用int32?
如果使用什么语言很重要,我只对C ++感兴趣。
答案 0 :(得分:3)
https://developers.google.com/protocol-buffers/docs/encoding#signed-integers
有符号变量通过在正值和负值之间交替进行编码。例如,
value int32 zigzag sint32
(binary) (binary)
0 00000000 0 00000000
-1 11111111 1 00000001
11111111
11111111
11111111
00001111
1 00000001 2 00000010
-2 11111110 3 00000011
11111111
11111111
11111111
00001111
...
63 00111111 126 01111110
-64 11000000 127 01111111
11111111
11111111
11111111
00001111
64 01000000 128 10000000
00000001
...
平均而言,正数需要再将一位编码为sint
而不是int
。
(展开并运行以下代码片段进行现场演示。)
function encode_varint(number) {
if (!number) return [0];
var bytes = [];
while (number) {
var byte = number & 0x7F;
number >>>= 7;
if (number) byte |= 0x80;
bytes.push(byte);
}
return bytes;
}
function format_bytes(bytes) {
var output = '';
for (var i = 0; i < bytes.length; i++) {
if (i) output += ' ';
output += bytes[i].toString(2).padStart(8, '0');
}
return output;
}
var valueElem = document.getElementById('value');
var int32Elem = document.getElementById('int32');
var sint32Elem = document.getElementById('sint32');
function update() {
var value = parseInt(valueElem.value);
var int32 = encode_varint(value);
var sint32 = encode_varint(value << 1 ^ -(value < 0));
int32Elem.value = format_bytes(int32);
sint32Elem.value = format_bytes(sint32);
}
valueElem.addEventListener('change', update);
update();
&#13;
#varint {
display: grid;
grid-template-columns: max-content auto;
grid-row-gap: 1ex;
grid-column-gap: 1ch;
}
#varint label {
text-align: right;
}
#varint input {
font-family: monospace;
}
&#13;
<form id='varint' onsubmit='return false'>
<label for='value'>value</label>
<input id='value' type='number' value='0'>
<label for='int32'>int32</label>
<input id='int32' type='text' readonly>
<label for='sint32'>sint32</label>
<input id='sint32' type='text' readonly>
</form>
&#13;
答案 1 :(得分:2)
一些正值将小于int32而不是sint32,但最多只有一个字节。
基本上,protobuf使用&#34; base128&#34;对数字进行编码,其中编码值的每个字节具有7位值数据,并且一位作为&#39;结束&#39;标记以查找编码值的结尾。 &#34; INT32&#34;将数字视为32位二进制补码并将其编码为无符号32位数,因此负值将被编码为大正值并始终需要5个字节。 &#34; SINT32&#34;另一方面,编码为奇怪的符号 - 幅度样式编码,符号位转换为最低有效位(为什么他们没有使用普通的2s补码是一个谜 - 将同样紧凑,但更简单到解码/编码)。
结果是单个字节int32可以表示0-127范围内的数字,而单个字节sint32表示范围为-64..63的数字。因此值64..127将需要2个字节作为sint32,并且只需要一个作为int32