Eratosthenes的筛子 - HeapMemoryOutOfSpace

时间:2014-11-27 17:34:54

标签: java error-handling heap-memory sieve-of-eratosthenes

所以我写了一个代码来实现eratosthenes的筛选,它适用于小输入!!一旦我接近1000000000它显示和错误,HeapMemoryOutOfSpace。我在这里一块,无法弄清楚如何让它为这么大的值工作。有没有可以为此做的某种优化?这是针对在线评判的,因此n的最大值是我已经提到过的。这不适用于比赛,仅适用于我自己的练习。任何形式的帮助将不胜感激!

import java.io.*;
class PrimeGenerator
{
public static void main(String args[])
{
    try
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int t = Integer.parseInt(br.readLine());

        while(t--!=0)
        {
            String k[] = br.readLine().split(" ");

            int m = Integer.parseInt(k[0]);
            int n = Integer.parseInt(k[1]);

            long arr[] = new long[n+2];

            for(long a=2;a<=n;a++)
            {
                arr[(int)a] = 1;
            }

            for(long a=2;a*a<=n;a++)
            {
                if(arr[(int)a]==1)
                {
                    for(long b=a;b*a<=n;b++)
                    {
                        arr[(int)(a*b)]=0;
                    }
                }
            }

            for(int a=2;a<=n;a++)
            {
                if(arr[a]==1&&arr[a]>=m)
                {
                    System.out.println(a);
                }
            }
            System.out.println();
        }
    }
    catch(Throwable e)
    {
        e.printStackTrace();
    }

}
}

3 个答案:

答案 0 :(得分:1)

操作已经指出了代码的几个结构性问题;程序的某些部分根本没有任何意义(如if (arr[a] == 1 && arr[a] >= m))。更不用说代码没有实现Eratosthenes的Sieve,即使它使用类似的逻辑。 Eratosthenes通过从指数p * p开始然后以p递增(即,相加步幅)来击出素数p的倍数。

两个观察结果,假设这类似于SPOJ PRIME1 problem,你必须在M和N之间打印素数:

(1)您使用一个64位整数(Java long)来表示每个候选编号而不是一个位。通过从阵列中排除所有偶数,可以进一步节省空间和时间,必要时可以用空气拉出数字2。比特打包,仅赔率表示只需要您现在使用的空间的1/128。在java.util.BitSet已经为您完成了艰苦的工作。

(2)为了筛选[M,N]范围内的数字,没有必要筛选2(或3)和N之间的所有数字。事实上,像SPOJ这样的任务是为了让你有时间超时尝试一下,即使它可以使用干净的高性能代码。对于筛选范围[M,N],您只需要所有潜在的素因子(最多sqrt(N) - 只有几千个)和一个大小为(N-M+1)的数组用于实际筛分。或(N-M)/2,仅用于赔率筛选。这只需要几毫秒而且空间不大。

对于SPOJ,您甚至不必使用打包位表示或仅限赔率筛选。只需专注于窗口筛分,您就可以轻松地完成任务,节省空间和时间。

答案 1 :(得分:0)

您需要调整JVM并增加堆大小。

如果您在控制台中运行程序,可以像这样增加大小:

java -Xmx6g myprogram

此命令将堆大小增加到6千兆字节,无论您的系统能够处理什么,都会增加它。

如果您正在运行eclipse或其他IDE,则必须查找如何调整JVM以在IDE中运行该程序,但它可能类似于上面的命令。

答案 2 :(得分:0)

对于高达1000000000的素数,您不需要在正确的实现中增加堆大小 您实施Eratosthenes筛选的一些问题:

  • 为什么在存储0和1时使用long? 有一种原始类型只使用0和1(假和真)称为布尔值。

  • 为什么要重新计算每一个素数?
    您可以计算每个单个素数一次(最多为整数最大数),然后只需检查列表或打印它们。