使用大数的Eratosthenes算法的Java筛时出现奇怪的数值错误?
我遇到了一个最奇怪的问题,调试它的时间很糟糕。我想我会把它贴在这里,征求意见使用大数的Eratosthenes算法的Java筛时出现奇怪的数值错误?,java,algorithm,memory,numerical-methods,Java,Algorithm,Memory,Numerical Methods,我遇到了一个最奇怪的问题,调试它的时间很糟糕。我想我会把它贴在这里,征求意见 public static void sieve(int limit) { for (int i = 2; i < limit; i ++) { if (mPrimes[i] == true) { for (int j = i*i; ((j < limit) && (j > 0)); j += i) {
public static void sieve(int limit) {
for (int i = 2; i < limit; i ++) {
if (mPrimes[i] == true) {
for (int j = i*i; ((j < limit) && (j > 0)); j += i) {
mPrimes[j] = false;
}
}
}
}
与
至于直接从种子值开始“划掉”,而不是从平方开始(这是我的教授在他的示例代码中所做的),它是有效的
这让我只能假设,当我非常大的时候,广场上发生了一些奇怪的事情
有什么建议吗 这是一个溢出错误。1000000*1000000需要的比特数超过整数(2*32-1)所能容纳的比特数。你需要使用一个长的(2*64-1) 此外,为了避免溢出,外循环可以是这样的:
for(inti=2;i*i
,它会更快(因为limit
下的任何非素数都必须在sqrt(limit)
下至少有一个素数除数)如果i*i
超过一个限制,就没有必要跨越任何数字。因此,不要使用长整数,只需将变量strike\u limit
初始化为sqrt(i)
的上限,如果i
超过该限制,甚至不要尝试进入strike out循环。很抱歉,我对Java不太了解,无法用它编写代码,但这应该是
int strike_limit=(int)(sqrt((双)限制)+0.5);
if(mPrimes[i]&&i
这保证了在计算i²时不会出现溢出。仔细分析角点情况。变量i最初为2,每一步都会增加,因此它总是正值。变量j最初是i×i,它是正的,并且在每一步都增加正数i,因此j总是正的。为什么要在内部循环中测试j>0?是否尝试使用long而不是int?没有理由在第二个for语句中包含
j>0
。因为j是i的平方,它总是大于0,所以j也总是大于0。是的,这实际上是之前的修复,因为相同的错误(i*i溢出并创建了-2^31,仍然通过了<极限测试)。既然我已经解决了这个问题,我可以把它去掉
i*i
i+i
if (mPrimes[i] && i < strike_limit) {
for (int j = i*i; j < limit; j += i) {
mPrimes[j] = false;
}
}