Lua版本是5.1.4,详细信息如下:
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
print(string.format("where id = %d", "1596856742980208710"))
输出:
where id = 1596856742980208640
但是当将 %d
更改为 %s
时:
print(string.format("where id = %s", "1596856742980208710"))
输出:
where id = 1596856742980208710
这是什么意思?
最佳答案
这是一个名为 coercion 的 Lua“特性” : 如果需要数字,Lua 会将字符串强制转换为数字,反之亦然。 Lua 5.1 默认使用 double 作为唯一的数字类型,这可能会在强制转换大数字时导致精度损失。
考虑你的第一个例子:
print(string.format("where id = %d", "1596856742980208710"))
%d
显然需要一个数字。因此,字符串 "1596856742980208710"
被强制转换为数字;代码等同于
print(string.format("where id = %d", tonumber"1596856742980208710"))
在较新的 Lua 版本(5.3+)上,这会工作得很好,因为数字将被转换为 64 位有符号整数:
$ lua
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio
> tonumber"1596856742980208710"
1596856742980208710
但是 Lua 5.1 没有整数类型;它会将数字转换为 64 位 double :
$ lua5.1
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> =("%d"):format(tonumber"1596856742980208710")
1596856742980208640
如您所见,数字已更改。这是因为 double 问题:可以存储在 double 中的最大安全整数是 2^53 - 1(参见例如 JS 的 MAX_SAFE_INTEGER
)。您的数字明显超过:将 9.007199254741e+15
与 1596856742980208710
进行比较。这会导致不太重要的小数位精度下降。当数字随后使用 %d
格式化时,您会得到不正确的结果。
你的第二个例子:
print(string.format("where id = %s", "1596856742980208710"))
显然有效,因为它将 "1596856742980208710"
视为字符串,并且首先不会将其强制转换为数字。因此,无论 Lua 版本如何,它都等同于字符串连接 "where id = ".. "1596856742980208710"
(因为 "1596856742980208710"
不包含 NULL 字节)。
关于lua - 使用 string.format 将字符串值转换为长数字,遇到一个奇怪的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72845042/