Поэтому я пытаюсь написать программу для решения проблемы Project Euler с наибольшим основным фактором, и, хотя я знаю, что код является структурно правильным (поскольку он возвращает правильные ответы для меньших чисел, включая пример 13195, который они дают), я продолжайте получать ошибку сегментации, когда я вводим номер, который мы должны решить, то есть 600851475143. Код выглядит следующим образом:
#include <stdio.h>
#include <math.h>
main(){
int number,a,b,c,i,j,n,gpf;
printf("Input number to analyze: ");
scanf("%d",&number);
a = number/2;
printf("%d\n",a);
int* primesieve = new int[a+1]; /*IMPORTANT LINE*/
for (i=0;i<a+1;i++){
primesieve[i] = 1;
}
for (j=2;j<=a;j++){
if (primesieve[j] == 1){
for (c=2;j*c<=a;c++){
primesieve[j*c] = 0;
}
}
}
for (n=2;n<=a;n++){
b = number/n;
printf("%d\n",b);
if (number % n == 0){
if (primesieve[b] == 1){
gpf = b;
n = a+1;
}
}
}
delete[] primesieve;
printf("The greatest prime factor of %d is %d.\n",number,gpf);
}
Проблема возникает из инициализации массива для простого сита, потому что я пропустил все строки после этого и все еще столкнулся с проблемой. Я изначально объявлял массив, используя следующий код, который возвращал ошибку сегментации для значений до 10 миллионов.
int primesieve[a+1];
Я искал решение на этом сайте, которое дало изменение динамическому распределению массива, но в то время как это разрешило проблему на 10 миллионов, это, по-видимому, не для значительно больших значений. Другие решения, которые я заметил, упоминали что-то об использовании malloc() или объявлении массива статически вне main(), но, откровенно говоря, я не понимал, что это мой вводный класс программирования, который едва упоминался malloc(), и я думал, что код, предшествующий объявлению массива, который должен содержаться в main(). (Для справки: ошибка сегментации при создании больших массивов в C и Seg Fault при инициализации массива.) Я уверен, что это довольно простая проблема, но я относительно новый программист и, следовательно, плохо разбираюсь в распределении памяти, поэтому любое предложение, решение или объяснение других решений, которые я нашел, будет с благодарностью оценено.
Ваш опыт связан с физическими ограничениями и точностью вашего компилятора. Первая попытка, выделяющая массив в стеке
int primesieve[a+1];
быстро не удалось, поскольку в большинстве систем стек довольно ограничен по размеру по сравнению с кучей.
Выделение на кучу
int* primesieve = new int[a+1];
дает вам больше места, но у вас все еще есть предел адресной памяти. Теперь, 600851475143 - довольно большое число, даже если вы разделите его на 2. И если размер int
равен 4 байтам, вы можете подумать, действительно ли вы можете решить эту большую память. С 32 битами вы можете адресовать 2 ^ 32 = 4294967296 байт.
Переполнение!
Он не может выделить размер массива 600851475143
в вашей памяти. В 32-битной системе требуется 4 4,476 GB
.
600851475143 * sizeof(int64_t) = 4806811801144 = 4.4TB
Другими словами, этот код всегда будет сбой, если у вас нет 5 ТБ ОЗУ.
Вы можете сделать его более терпимым, если вы используете растровое изображение для вашего сита. Например, использование 1 бит на номер, а не отображение четных чисел, требует только 600851475143/8/2
= 35GB
ОЗУ. Еще много, но возможно, если у вас есть деньги на оборудование.