埃拉托色尼执行筛

Sieve of Eratosthenes implementation

本文关键字:执行 埃拉托      更新时间:2023-10-16

我正在尝试实现Eratosthenes筛算法,但我不知道为什么这个程序崩溃较大的程序。最初我使用的是vector,但现在我使用动态内存分配来实现它。

#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
unsigned isqrt(unsigned value) {
  return static_cast<unsigned>(sqrt(static_cast<float>(value)));
}
int main()
{
    int t;
    cin >> t;
    long long * N;
    long long * M;
    long long n, m;
    N = new long long[t];
    M = new long long[t];
    for(int i = 0; i < t ; i++){
        cin >> M[i] >> N[i];
    }
    for(int i = 0; i < t ; i++){
        n = N[i];
        m = M[i];
        bool * A;
        A = new bool[n];
        if(A == 0)
        {
            cout << "Memory cannot be allocated";
            return 0;
        }
        for(int i=0;i < n;i++){
            A[i]=true;
        }
        A[0] = false;
        A[1] = false;
        unsigned sqrt = isqrt(n);
        for(int i = 2; i <= sqrt; i++)
        {
            if(A[i] == true){
                for(int j = i*i; j <= n; j = j + i)
                {
                    A[j] = false;
                }
            }
        }
        for(int i = m;i < n;i++)
        {
            if(A[i] == true )
                cout << i << "n";
        }
        delete[] A;
    }
    delete[] M;
    delete[] N;
    return 0;
}

nm值较大(~10^16)时,程序崩溃。

for(int j = i*i; j <= n; j = j + i)
                   ^^

如果j == nA[j] = false将赋值给数组末尾之后的元素。测试应该是j < n

如果你打算用c++写一个Eratosthenes的脚本,那么如果你真的使用 c++,而不是试图将其视为C语言和汇编语言之间的某种疯狂的交叉呢?

#include <vector>
#include <iostream>
unsigned long primes = 0;
int main() {
    int number = 10000000;
    std::vector<bool> sieve(number,false);
    sieve[0] = sieve[1] = true;
    for(int i = 2; i<number; i++) {
        if(!sieve[i]) {
            ++primes;
            for (int temp = 2*i; temp<number; temp += i)
                sieve[temp] = true;
        }
    }
    std::cout << "found: " << primes << " Primesn";
    return 0;
}

如果n大到足以导致内存分配错误,程序将由于不正确的内存分配错误处理而崩溃

 A = new bool[n];
        if(A == 0)
        {
            cout << "Memory cannot be allocated";
            return 0;
        }

new在错误时不会返回0,但会抛出std::bad_alloc,而该std::bad_alloc没有被捕获,这反过来会导致调用unexpected()、terminate()和abort()。
正确的版本应该是:

  try
  {
    A = new bool[n];
  }
  catch (std::bad_alloc& ba)
  {
    std::cerr << "Memory cannot be allocated: " << ba.what() << 'n';
  }

在调试器中运行此命令以确定崩溃的位置并从那里进行调试。到那时,它很可能是显而易见的。

您可以从IDE或从命令行执行此操作。在后一种情况下,使用-g编译并在gdb之类的程序中运行。你可以在谷歌上搜索"gdb备忘单"之类的东西。