Мой код работает отлично, если seive (n) равен 1000000. Если seive (n) больше, чем 10000000, это показывает мне ошибку сегментации (ядро сбрасывается). Я прочитал об ошибке сегментации. Но я не мог с этим справиться.
#include <stdio.h>
#include <math.h>
using namespace std;
int seive(long int n)
{
long int A[n];
for (long int i = 2; i <= n; i += 1)
{
A[i] = i;
}
long int root = (int)sqrt(n);
for(int j = 2; j <= root; j++)
{
for(int k = 2*j; k < n ; k = k + j)
{
A[k] = 0;
}
}
int count = 0;
for (int l = 2; l < n; ++l)
{
if(A[l] != 0) count++;
}
printf("%d\n", count);
}
int main()
{
seive( 1000000);
}
long int A [n];
Это массив в стеке. Это действительно большой, если N большой. Ваш стек недостаточно велик, чтобы удерживать его в этих случаях, и вы получите ошибку.
Решения включают:
Динамическое выделение памяти: long int * A = (long int *) malloc (n * sizeof (long int));
Динамическое выделение памяти C++ style: long int * A = новый long int [n];
Использование статически выделенного буфера (то есть не в стеке): static long int A [n];
Сделать это глобальным: переместите эту линию на 3 строки.
n
передается в; не фиксированная константа.
То, что вы пытаетесь сделать, это попытаться выделить массив с большим количеством элементов в стеке (стек памяти)
long int A[n];
В общем случае вы сможете выделить более крупный массив в куче, используя
int *A = new int[n]
Ваше автоматическое хранилище облагается за его пределы на вашей платформе по ряду причин.
Во-первых, каждый элемент бесполезен на 63 бита больше, чем нужно, предполагая, что ваша платформа unsigned long int
равна 64 бит. Сито обычно должно представлять только одно из двух значений: "true" или "false". Для этого достаточно массива bool
с некоторой незначительной настройкой вашего алгоритма.
Во-вторых, хотя первый элемент важен, он не является доминирующим фактором в размере вашего массива. Эта привилегия принадлежит n
, верхнему пределу вашего квеста. Ваш запрос на значительное количество места в автоматическом хранилище. Предполагая, что вы обратились к первому и представление bool
на вашей платформе - это один байт, флажок-массив из 10000000
записей все равно потребует ок. 9,54 МБ автоматического хранилища, которое не смешно.
Решение представляет собой динамическое хранилище и может быть выполнено несколькими способами, некоторые из которых:
malloc(sizeof(bool)*(n+1))
(обескуражен в современных C++ программах)new bool[n+1]]
(лучше, но все же не очень)std::vector<bool>
(теперь мы куда-то получаем) Ниже показан очень простой пример сита, который использует приведенное выше. Вы можете значительно улучшить это с оптимизированной логикой относительно четных чисел (не нужно даже их хранить) и т.д. Но это не главное. Точка использует динамическое хранилище, желательно что-то с автоматическим временем жизни, которое std::vector<>
делает для вас красиво.
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
unsigned long int sieve(unsigned long int N)
{
std::vector<bool> vec(N+1,true);
unsigned long int res = 1;
const unsigned long int SR = std::floor(std::sqrtl(static_cast<long double>(N)));
for (unsigned long int i=2; i<=SR; ++i)
{
if (vec[i])
{
++res;
for (unsigned long int j=(i << 1); j<=N; j+=i)
vec[j] = false;
}
}
for (unsigned long int i=SR+1; i<=N; ++i)
{
if (vec[i])
++res;
}
return res;
}
int main()
{
std::cout << sieve(10000000) << '\n';
return 0;
}
Вывод
664580
который, по моему мнению, верен, если вы не относитесь к тому, что игнорирует 1
(некоторые делают, не знаю почему), и в этом случае это одно.
10000000 * sizeof(long int)
.