网易乐得技术团队

Protobuf lua int64 repeated 数字越界问题

LUA 本身的number 支持范围

大家知道 LUA里面只有number 类型,那么number类型的范围是多少呢:[-math.pow(2, 1023) , math.pow(2, 1023)]

1
2
3
4
5
6
7
8
9
10
11
>Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
>return math.pow(2, 1024)
inf
> return math.pow(2, 1023)
8.9884656743116e+307
> return -math.pow(2, 1023)
-8.9884656743116e+307
> return -math.pow(2, 1024)
-inf
> return math.pow(2, 1024)
inf

那么精确的整型表达又是多少呢:math.pow(2, 53)
http://lua-users.org/wiki/NumbersTutorial

1
2
3
4
> return string.format("%020d", -math.pow(2, 53))
-0009007199254740992
> return string.format("%020d", math.pow(2, 53))
00009007199254740992

Protobuf int 的类型有int32、int64

protobuf int32的取值范围是math.pow(2, 31) = 2147483648
protobuf int64的取值范围是math.pow(2, 63) = 9223372036854775807

但是上文中提到lua里面精确的整型的范围是math.pow(2, 53) = 9007199254740992
所以大家在使用LUA中int64的注意一下,别超过9007199254740992
但是大家需要注意一下,如果大家使用大牛 林卓毅protoc-gen-lua
https://github.com/sean-lin/protoc-gen-lua

举个例子,大家看一下下面的message
如果coin大于2^31,小于2^53,使用protoc-gen-lua可以解析出来,但是如果repeated betNums里面如果有一个数大于2^31那么就会导致Value out of range,大家可以参考一下:
protobuf/type_checkers.lua:Int32ValueChecker 函数
protobuf/containers.lua:append 函数

1
2
3
4
5
message Info { 
required string id = 1;
required int64 coin = 2;
repeated int64 betNums = 3;
}

所以在使用protoc-gen-lua repeated int64 参数的时候不要超过math.pow(2, 31) = 2147483648

ps: 如果非要使用repeated int64 超过2147483648,大家可以添加Int64ValueChecker,但是取值范围不要超过math.pow(2, 53)