我正试图找到Pólya Conjecture的反例,它将在9亿的某个地方。我正在使用一种非常有效的算法,甚至不需要任何分解(类似于Eratosthenes的Sieve,但有更多的信息。因此,需要大量的整数。
该程序高效且正确,但需要一个阵列,直到我要检查的x(它检查来自(2,x)的所有数字)。所以,如果反例是9亿,我需要一个同样大的数组。 Java不会允许我超过2000万。有什么我可以做的让阵列变大吗?
答案 0 :(得分:12)
您可能希望扩展JVM堆的最大大小。您可以使用命令行选项来执行此操作。
我相信它是-Xmx3600m(3600兆字节)
答案 1 :(得分:10)
Java将允许最多2亿个数组条目。这是你的机器(和你有限的记忆)无法处理这么大的数量。
答案 2 :(得分:10)
Java数组由int索引,因此数组不能大于2 ^ 31(没有无符号整数)。因此,数组的最大大小为2147483648,消耗(对于普通的int [])8589934592字节(= 8GB)。
因此,int-index通常不是限制,因为无论如何你都会耗尽内存。
在算法中,您应该使用List(或Map)作为数据结构,并选择List(或Map)的实现,它可以超过2 ^ 31。这可能会变得棘手,因为“通常”实现ArrayList(和HashMap)在内部使用数组。您必须实现自定义数据结构;例如通过使用2级数组(列表/数组)。当你在它时,你也可以尝试更紧密地包装。
答案 3 :(得分:7)
9亿32位整数没有进一步的开销 - 并且总会有更多的开销 - 需要略高于3.35 GiB。获得大量内存的唯一方法是使用64位JVM(在具有至少8 GB RAM的计算机上)或使用一些磁盘备份缓存。
答案 4 :(得分:6)
如果您不需要将所有内容一次性加载到内存中,则可以将其分割为文件并存储在磁盘上。
答案 5 :(得分:2)
“不允许”是什么意思。您可能得到OutOfMemoryError
,因此使用-Xmx
命令行选项添加更多内存。
答案 6 :(得分:1)
您可以定义自己的类,该数据将数据存储在2d数组中,该数组与sqrt(n)更接近sqrt(n)。然后使用索引函数来确定数组的两个索引。根据需要,这可以扩展到更多维度。
您将遇到的主要问题是RAM耗尽。如果您达到此限制,则需要重新考虑算法或考虑外部存储(即文件或数据库)。
答案 7 :(得分:1)
如果您的算法允许:
在适合内存的切片中进行计算。
你必须重做每个切片的计算,但它通常足够快。
使用较小数字类型的数组,例如byte。
答案 8 :(得分:1)
根据您访问阵列的方式,您可能会发现RandomAccessFile允许您使用大于内存的文件。但是,您获得的性能非常依赖于您的访问行为。
答案 9 :(得分:0)
我为Euler项目编写了一个版本的Eratosthenes筛选器,它一次处理搜索空间的块。它处理前1M个整数(例如),但保留它在表中找到的每个素数。在遍历到目前为止发现的所有素数之后,重新初始化数组,并且在找到下一个数组之前已经使用已经找到的素数来标记数组。
该表将素数映射到数组起始处的“偏移量”,以便进行下一次处理迭代。
这在概念(如果不是在实现中)与函数式编程语言执行列表的惰性评估的方式类似(尽管在更大的步骤中)。不需要预先分配所有内存,因为您只对通过测试的数组部分感兴趣。保持非素数不变对你没用。
此方法还为以后的素数迭代提供了备忘。它比扫描稀疏的筛子数据结构更快,每次都在寻找那些。
答案 10 :(得分:0)
我的第二个@ sfossen的想法和@Aaron Digulla。我会去磁盘访问。如果您的算法可以接受List接口而不是普通数组,则可以将List中的适配器写入内存映射文件。
答案 11 :(得分:0)
使用Tokyo Cabinet,Berkeley DB或任何其他基于磁盘的键值存储。它们比任何传统数据库都快,但允许您使用磁盘而不是内存。
答案 12 :(得分:0)
答案 13 :(得分:-1)
您可以尝试将其拆分为多个数组。
for(int x = 0; x <= 1000000; x++){
myFirstList.add(x);
}
for(int x = 1000001; x <= 2000000; x++){
mySecondList.add(x);
}
然后迭代它们。
for(int x: myFirstList){
for(int y: myFirstList){
//Remove multiples
}
}
//repeat for second list
答案 14 :(得分:-2)
使用内存映射文件(Java 5 NIO包)。或者将筛子移动到一个小的C库中并使用Java JNI。