lua - 使用 string.format 将字符串值转换为长数字,遇到一个奇怪的问题

标签 lua

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+151596856742980208710 进行比较。这会导致不太重要的小数位精度下降。当数字随后使用 %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/

相关文章:

error-handling - lua 递归 repl 错误?

sql - 将sql行id传递给corona中的tableview

lua - 我的 if-then-else-end 语句在 Lua 中失败了;我该如何修复它?

macos - luac.out : incompatible precompiled chunk

android - 电晕 : Check nil value before call onComplete event

ubuntu - 如何在 Luci openwrt sys.exec() 函数中传递命令行参数?

visual-c++ - 从另一个线程调用 lua 函数(作为回调)是否足够安全?

替换 lua 中的键的表值

arrays - 在Lua中将数组作为函数参数传递?

lua - 是否可以在 Lua 中模拟绑定(bind)?