我正在尝试在Lua中构建一个Sieve of Eratosthenes,我尝试了几件事,但我发现自己遇到了以下问题: 对于这种情况,Lua的表格很小。如果我只想创建一个包含所有数字的表格(参见下面的示例),即使只有1/8(...)的数字,表格也太“小”(我承认这个数字非常大)...
max = 600851475143
numbers = {}
for i=1, max do
table.insert(numbers, i)
end
如果我在Windows计算机上执行此脚本,则会显示一条错误消息:C:\Program Files (x86)\Lua\5.1\lua.exe: not enough memory
。随着Lua 5.3在我的Linux机器上运行我也尝试了,错误只是killed
。因此很明显,lua无法处理条目数量。
我真的不知道是否只是不可能在lua表中存储那些数量的条目,或者有一个简单的解决方案(通过使用长字符串尝试它...)? Lua表中最大的条目数究竟是什么?
更新:是否可以为表格手动分配更多内存?
更新2(第二个问题的解决方案):第二个问题很简单,我只是通过运行每个数字来测试它,直到程序中断: 33.554.432 (2 ^ 25)条目适合我的12 GB RAM系统中的一个一维表。为什么2 ^ 25?因为64位每个数字* 2 ^ 25 = 2147483648位正好是2 GB。这似乎是Lua for Windows 32 Bit编译器的标准内存分配大小。
P.S。您可能已经注意到这个数字来自欧拉项目问题3.是的,我正在努力实现这一目标。请不要给出具体的提示(..)。谢谢:))
答案 0 :(得分:1)
Lua使用双精度浮点数来表示数字。这是每个数字64位。 600851475143数字导致近4.5TB的内存。
所以这不是Lua或其表的错。错误消息甚至说
内存不足
你只是没有足够的RAM来分配那么多。
如果你仔细阅读了链接的维基百科文章,你会发现以下部分:
正如Sorenson指出的那样,Eratosthenes筛子的问题不是 它执行的操作数量,而不是内存 的要求即可。[8] 对于大n,素数范围可能不适合 的存储器强>;更糟糕的是,即使是适度的n,它的缓存使用率也很高 次优的。该算法遍历整个阵列A,展示 几乎没有参考地点。
分段筛子提供了解决这些问题的方法,其中 只有部分范围一次过筛。[9]这些都是 自20世纪70年代以来就已知,并且工作如下 ...
答案 1 :(得分:1)
Eratosthenes的Sieve只需要每个数字一位,表示该数字是否已被标记为非素数。
减少内存使用的一种方法是使用按位数学来表示每个表条目中的多个位。当前的Lua实现具有对bitwise-or,-and等的内在支持。根据底层实现,您应该能够为每个表条目表示32位或64位(数字标志)。
另一种选择是使用一个或多个非常长的字符串而不是表。你只需要一个线性数组,这正是一个字符串。只要在每个位置都有一个带“t”或“f”或“0”或“1”的长字符串。
警告:Lua中的字符串操作总是涉及重复,在性能方面会迅速变为n²或更复杂。你不希望整个大规模序列有一个连续的字符串,但是你可以把它分解成一千块或一些2的幂。这会将你的内存使用量减少到每个数字1个字节,同时最小化开销。
编辑:在注意到其他地方的观点之后,我意识到您的最大数量是如此之大,以至于即使每个数字都有一点,您的内存要求也会达到 73千兆字节强>,这是非常不切实际的。我建议按照Piglet在他们的答案中给出的建议来看看Jon Sorenson的筛子版本,它适用于空间的各个部分而不是整个部分。
我会留下我的建议,因为它仍然可能对索伦森的筛子有用,但是,你有一个比你意识到的更大的问题。