lua - floor(a, b) 和 a // b 的结果不同
问题描述
--this function isn't relevant, but I included it for completeness
function gcd(a, b)
local temp
while b > 0 do
temp = a % b
a = b
b = temp
end
return a
end
function extendedgcd(a, b)
if b == 0 then
return 1, 0, a
end
local x, y, d = extendedgcd(b, a % b)
--this assertion fails for a = 568784642688024576, b = 5
--left side gives 113756928537604915 (correct), while right side gives 113756928537604912 (wrong)
assert(a // b == math.floor(a / b))
--so here, I can't use math.floor
return y, x - a // b * y, d
end
function modularinverse(e, mod)
if gcd(e, mod) > 1 then
return nil
end
local x, _, _ = extendedgcd(e, mod)
if x < 0 then
x = x % mod
end
if x * e % mod ~= 1 then
error(string.format("Modular inverse (%d) doesn't produce 1 (e = %d, mod = %d)", x, e, mod))
end
return x
end
modularinverse(5, 568784642688024576)
对于a = 5
和b = 568784642688024576
,中的断言extendedgcd
失败。我不是 FP 精度方面的专家,但两者之间的差异为 3,所以我认为这里不存在舍入/精度错误。但我可能错了。
通常我只会使用//
,但我不能,因为目标平台没有运行 Lua 5.3,这是添加操作员的时候。
我错过了什么?我如何使它与 一起工作floor
,或者有其他方法吗?
另外值得注意的是:当我用 Python 重写它来摆弄(使用math.floor
and //
)时,也发生了同样的问题。
解决方案
更准确的答案:
正如纸和铅笔将显示的那样:
568784642688024576 / 5 = 113756928537604915.02
该商作为双精度数的最准确二进制表示是:
0100001101111001010000100101010100101110010000111001001100110011
其中,十进制是:(1.13756928537604912E17
注意 ...912 结尾)
现在,如果将二进制表示减一,如下所示:
0100001101111001010000100101010100101110010000111001001100110010
然后它等于:(1.13756928537604896E17
最后...896!)
如果要将原始二进制数加一,如下所示:
0100001101111001010000100101010100101110010000111001001100110100
然后等于:(1.13756928537604928E17
最后...928!)
因此,这些数字有精确的双精度二进制表示:
113756928537604896
113756928537604912
(最接近实际商数)
113756928537604928
以上可以使用在线转换器进行验证,例如这里。
所以教训是:
整数除法将给出正确答案(即商的整数部分)。地板浮点除法依赖于数字的二进制表示,这并不总是精确的。
在此答案的范围之外,但需要阅读才能真正理解其中的任何内容:
上述二进制数如何表示它们的十进制等值?
- 简短回答:IEEE-754。如果您打算研究该标准文件,我祝您好运和喝咖啡。
/
和之间的算法区别是什么//
?
- 换句话说,为什么
//
上面得到了我们想要的答案?
推荐阅读
- xslt - 排序后如何使用XSL获取第一个孩子
- python - JSONDecodeError:期望值:执行大型 API 请求时的第 1 行第 1 列(字符 0)
- android - Android SQLite SELECT SUM 按特定列过滤
- java - 使用GMM和EM算法进行图像分割java
- c# - visual studio 2015 警告:无法读取与解决方案关联的某些属性
- javascript - 在 chrome 扩展中加载特定页面时创建弹出对话框
- excel - VBA-一个定时器功能,一步一步地捕捉经过的时间
- r - groupby 在 groupby dplyr 之外总结
- python - 有没有办法将 scipy.stats.normaltest 应用于整个数据帧?
- javascript - 当我在提交按钮中使用 onclick 事件提交表单时,preventDefault 不起作用