sieve upto 2 billion gives segmentation fault - c++

I am using this program to check a number if prime or not.
Use algorithm - Sieve :
#include<bits/stdc++.h>
//#define _max 2000000001
#define _max 20000001
using namespace std;
bool sieve[_max];
void init()
{
memset(sieve,true,sizeof(sieve));
sieve[0]=sieve[1]=false;
for(int i=2;i<_max;i+=2)
{
sieve[i]=false;
}
}
void go_sieve(int n)
{
n++;
for(int i=3;i<n;i+=2)
{
if(sieve[i]==false)
continue;
for(int j=2*i;j<n;j+=i)
sieve[j]=false;
}
}
void print(int n)
{
n++;
printf("-------------\n");
for(int i=0;i<n;i++)
{
if(sieve[i])
cout << i << " ";
}
printf("\n-------------\n");
}
int main()
{
init();
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
go_sieve(x);
//print(x);
if(sieve[x])
printf("Prime\n");
else
printf("Not prime\n");
}
return 0;
}
Now it works upto 2e7 and pretty smoothly, but I want to check upto 2e9, if I change my _max to 2000000001 it gives me segmentation error and exits with an error code.
How can I resolve this problem ?
I have tried a new approach with set :
#include<bits/stdc++.h>
//#define _max 200001
//#define _max 20000001
#define _max 2000000001
using namespace std;
set<int>prime;
set<int>nprime;
void init()
{
prime.insert(2);
}
void go_sieve()
{
for(int i=3;i<_max;i+=2)
{
if(prime.find(i)==prime.end() && nprime.find(i)==nprime.end())
{
prime.insert(i);
//cout << i << endl;
for(int j=2*i;j<_max;j+=i)
nprime.insert(j);
}
if(nprime.find(i)!=nprime.end())
nprime.erase(nprime.find(i));
}
}
void print()
{
set<int> ::iterator itt;
printf("-------------\n");
for(itt=prime.begin();itt!=prime.end();itt++)
{
cout << *itt << " ";
}
printf("\n-------------\n");
}
int main()
{
init();
go_sieve();
//print();
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
if(prime.find(x)!=prime.end())
printf("Prime\n");
else
printf("Not prime\n");
}
return 0;
}
Target is to execute it within 512MB~1GB memory.

If you want to enumerate large ranges of prime numbers, you should use a segmented Sieve of Eratosthenes; it will be faster (due to caching effects) and use less memory.
If you only want to determine if one number is prime, or a few numbers, sieving is a horrible way to do it. Sieving should only be used when you are interested in an entire range of numbers. For n up to a billion, trial division is simple and probably fast enough. For larger numbers, a Miller-Rabin test or Baillie-Wagstaff test is probably better.

I can't reproduce this on my system. My guess is that this has to do with a system dependant limitation.
You declare sieve as a global array (static storage duration) and it's huge (i.e. 2000000001 * sizeof(bool) - could be 2-8G depending on sizeof bool). Maybe your system can't handle that.
Instead of a global array, try using dynamic allocation:
// bool sieve[_max]; comment out this
bool* sieve = NULL;
...
...
int main()
{
sieve = (bool*)malloc(_max * sizeof *sieve);
if (sieve == NULL)
{
// out of memory
exit(1);
}
...
That said:
Your code is C++ but your style is more C like.
In C++ you would probably use a std::vector instead. That would make everything much easier.
BTW: Also avoid globals. Instead define the vector (or dynamic array) in main and pass it by-reference to the functions.

You probably hit some memory limit on your system which causes the segmentation fault.
However, you don't need such a big array. Using Sieve of Eratosthenes, you need to calculate numbers up to x. Instead of an array you can use std::vector and increase its size as you calculate more numbers. This should allow you to calculate some numbers, but with large numbers you will hit the memory limit again.
You could also use some algorithm which requires you to store fewer numbers. To determine whether x is prime, you only need to compare against prime numbers that are smaller than the square root of x. You don't have to store numbers that are not primes. With x = 1e10, you would only need to store 5e8 numbers.
Here is some example with vector (probably not optimal):
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
std::vector<int> primes = {2};
void calculate(int x) {
const int largest_prime = primes.back();
if (largest_prime >= x) {
// Already calculated
return;
}
for (size_t i = largest_prime + 1; i <= x; i++) {
bool not_prime = false;
for (size_t j = 0; j < primes.size(); j++) {
if (i % primes[j] == 0) {
not_prime = true;
break;
}
}
if (!not_prime) {
primes.push_back(i);
}
}
}
bool check(int x) {
calculate(x);
return std::find(primes.begin(), primes.end(), x) != primes.end();
}
int main() {
std::cout << check(15) << std::endl;
std::cout << check(256699) << std::endl;
}

Related

Random Number Array/ minimum

#include <stdlib.h>
#include <cstdlib>
#include <ctime>
using namespace std;
int minimum(int zahlen[])
{
int minimum;
int o = 0;
bool prüf = false;
while (true)
{
for (int p = 0; p < 20; p++)
{
if (o == zahlen[p])
{
minimum = zahlen[p];
prüf = true;
}
}
if (prüf == true)
{
break;
}
o++;
}
return minimum;
}
void main()
{
srand(clock());
int array[20];
for (int i = 0; i < 20; i++)
{
array[i] = rand();
}
//Minimum
cout << "Die kleinste Zufallszahl die erstellt wurde ist die: " << minimum(array) << endl;
system("PAUSE");
}
Hi,
I have to create a 20 numbers long random array and check for the smallest number.
I know my code is probably not the best method to use for this problem but I am just always getting 371, 374, 202 or 208 as result. Never something else.
Is there a problem I don't see?
It most likely has to do with your use of clock(). According to this, clock() does not give you the current time. It gives you the time since your program started. So everytime you run this program, it takes roughly the same time for it to call clock(), meaning that the random seed is always about the same. To get the actual current world time, use std::chrono::system_clock::now() instead.
Also, an easier way of finding the minimum is this.
int minimum(int _randomNumbers[], int _arraySize)
{
int minimum = _randomNumbers[0]; // By default, let's assume the element 0 has the smallest number.
// Note that in this loop, i starts from 1, since there's no need to compare with element 0.
for (int i = 1; i < _arraySize; ++i)
{
if (_randomNumbers[i] < minimum)
{
minimum = _randomNumbers[i];
}
}
return minimum;
}

The check with the module in the loop doesn`t work

There is a task. It is necessary in a one-dimensional array of N real numbers to calculate the number of the maximum modulo element among unpaired numbers.
I wrote the code, but it does not work. I can’t understand what’s wrong with him.
#include <iostream>
#include <math.h>
using namespace std;
int main() {
setlocale(0, "");
const int KolEl = 5;
int mas[KolEl];
int max = abs(mas[0]);
int result;
for (int i = 0; i < KolEl; i++)
{
cout << " Введите елемент[" << i << "] = ";
cin >> mas[i];
if (mas[i] % 2 == 1) {
if (abs(mas[i]) > max) {
result = i;
cout << result << endl;
}
}
}
system("pause");
}
You initialize max as:
int mas[KolEl];
int max = abs(mas[0]);
However, the values in mas[] are garbage values (read: undefined behavior). So now the value in max is also UB.
You then go on to use that value to compare to the input you take:
if (abs(mas[i]) > max) {
So the result of that comparison is undefined.
You probably meant to declare max as something like:
int max = INT_MIN;
So that the first comparison will always be true (every int except INT_MIN will be greater than it).

Can someone help me with rectifying the output of this "Prime Numbers below 100" code?

This Question has been answered
So basically, I just wrote down a code to display all the prime numbers below 100. This is the code:
#include <iostream>
using namespace std;
int main()
{
int n=2,i;
cout<<"All Prime numbers below 100 are : \n";
while(n<=100)
{
for(i=2; i<n/2; i++)
{
if (n%i==0)
{
goto restart;
}
else
{
cout<<n<<"\t";
}
}
restart:
n++;
}
return 0;
}
But instead of the output being 2 3 5 7 11 ..... it comes out as:
All prime numbers below 100 are:
7 9 11 11 11 13 13 13 13 15 15 and so on ...
I just want the output to display all prime numbers starting from 2 to 97 without repetitions. thank you.
/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/--/-/-/-/-
I got out of the problem with a slight modification.
#include<iostream>
using namespace std;
int main()
{
int n=2, i;
while(n<=100)
{
for(i=2; i<=n/2; i++)
{
if(n%i==0)
{
goto label;
}
}
cout<<n<<", ";
label:
n++;
}
return 0;
}
Thank you to everyone for your valuable time. (And the reason why I use such beginner type codes is I've just started out on C++ like a week ago. I have so much more codes (like bool, isPrime, etc.) to learn.)
Keeping Cranking 'em codes, fellow coders :D
There is an obvious error in your algorithm. You might be able to find it using a debugger, but I think that a better way would be for you to learn about extracting a function. What you want your main function to do, is exactly: if n is prime: output n. So you should write it that way:
int main()
{
for (int i = 0; i < 100; ++i)
if (is_prime(i))
std::cout << i << std::endl;
}
Of course for that to work you'll need to define the function is_prime:
bool is_prime (int n) {
for (int i = 2; i * i <= n; ++i)
if (n % i == 0)
return false;
return true;
}
Note also that there is no need to check if n is divisible by numbers greater then it's square root. If there are no divisors up to the square root, the next possible divisor is n itself.
As others mentioned, that's not the optimal algorithm to solve this problem, but for small values it's definetely good enough.
Your answer is OK but has two critical errors. Firstly, you output n for each modulo you check. You should only output n if all the modulo checks fail. Also, your boundary condition isn't quite right - it should be <=. Working code with minimal changes would be:
#include <iostream>
using namespace std;
int main()
{
int n=2,i;
cout<<"All Prime numbers below 100 are : \n";
while(n<=100)
{
for(i=2; i<=n/2; i++)
{
if (n%i==0)
{
goto restart;
}
}
cout<<n<<"\t";
restart:
n++;
}
return 0;
}
If you wanted to make slightly cleaner code then dont use goto, use a double for loop and a break. Also your boundary condition for i should be i*i<=n as thats a tighter bound. So something like:
#include <iostream>
int main()
{
cout<<"All Prime numbers below 100 are : \n";
for(int n=2; n<100; ++n)
{
bool isPrime = true;
for(int i=2; i*i<=n; i++)
{
if (n%i==0)
{
isPrime = false;
break;
}
}
if(isPrime)
std::cout<<n<<"\t";
}
}
You are trying to check if each number is prime. Therefor you have to check if it is dividable by a smaller number.
A more efficient way to find all prime numbers up to a maximal number is the Sieve of Erathosthenes:
#include <iostream>
#include <vector>
int main() {
const unsigned int maxNum(100);
std::vector<bool> prime(maxNum, true);
for (unsigned int i(2); i*i < maxNum; ++i) {
if (!prime[i]) continue;
for (unsigned int j(2*i); j < maxNum; j += i) {
prime[j] = false;
}
}
for (unsigned int i(2); i < maxNum; ++i) {
if (prime[i]) std::cout << i << std::endl;
}
return 0;
}
A list of all numbers is created. Each multiple of of each number is removed from this list.

Finding minimum and maximum in a array c++

I have to find the minimum and maximum value of elements in a array using divide and conquer. I have written a code but it is not working for more then 6 elements in array. I don't know whats the problem
#include<iostream>
using namespace std;
int minimum=999,maximum,mi,ma;
void result(int mi,int ma)
{
if(maximum<ma)
{
maximum=ma;
}
if(minimum>mi)
{
minimum=mi;
}
}
void maxmin(int arr[],int i,int j)
{
cout<<" i ="<<i<<" j= "<<j<<endl;
if(i==j)
{
mi=ma=arr[i];
result(mi,ma);
}
else if(i==j-1)
{
if(arr[i]>arr[j])
{
ma=arr[i];
mi=arr[j];
}
else
{
mi=arr[i];
ma=arr[j];
}
result(mi,ma);
}
else
{
int mid=i+j/2;
maxmin(arr,i,mid);
maxmin(arr,mid+1,j);
}
}
int main()
{
int arr[10],n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
maxmin(arr,0,n-1);
cout<<" max "<<maximum<<" min "<<minimum<<endl;
return 0;
}
Your code has a few mistakes
Your code reads n from the user input, but you provided only 10 sized array, and user can try to input 10+ numbers, so we will have an undefined behavior in that case.
You write it very bad and unreadable. If you want somebody else to read your code, check in the your favourite book or in the internet information about how to write beautiful and readable code.
You implemented that algorithm yourself. It is a bad habit, use the standard library algorithms and you will not encounter such mistake.
.
#include <iostream> // std::cin, std::cout
#include <cstddef> // std::size_t
#include <algorithm> // std::min_element, std::max_element
int main ()
{
std::size_t array_size;
std::cin >> array_size;
int *some_array = new int[array_size]; // Allocate memory dynamically
for(std::size_t i = 0; i < array_size; ++i)
{
std::cin >> some_array[i];
}
/* Standard library operate on iterators, they are special classes
* that have interface that is similar in many cases to pointers (so we can use pointers as iterators).
* std::min/max_element needs one iterator for the sequence beginning
* and one iterator after the end. It returns iterator to a found element.
*/
int min = *std::min_element(some_array, some_array + array_size);
int max = *std::max_element(some_array, some_array + array_size);
delete[] some_array;
std::cout << "Min = " << min << std::endl << "Max = " << max;
std::cout << std::endl;
}
Code isn't well written and first dry run your code, you will find the problem easily.
Change
else
{
int mid=i+j/2;
maxmin(arr,i,mid);
maxmin(arr,mid+1,j);
}
To
else
{
int mid=(i+j)/2; /*** Adding brackets ***/
maxmin(arr,i,mid);
maxmin(arr,mid+1,j);
}
And check the logic for calling the result function (because according to your logic the two subsets are individually calculating MIN and MAX in itself not in whole array)

Algorithm to generate all permutation by selecting some or all charaters

I need to generate all permutation of a string with selecting some of the elements. Like if my string is "abc" output would be { a,b,c,ab,ba,ac,ca,bc,cb,abc,acb,bac,bca,cab,cba }.
I thought a basic algorithm in which I generate all possible combination of "abc" which are {a,b,c,ab,ac,bc,abc} and then permute all of them.
So is there any efficient permutation algorithm by which I can generate all possible permutation with varying size.
The code I wrote for this is :
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
using namespace std;
int permuteCount = 1;
int compare (const void * a, const void * b)
{
return ( *(char*)a - *(char*)b);
}
void permute(char *str, int start, int end)
{
// cout<<"before sort : "<<str;
// cout<<"after sort : "<<str;
do
{
cout<<permuteCount<<")"<<str<<endl;
permuteCount++;
}while( next_permutation(str+start,str+end) );
}
void generateAllCombinations( char* str)
{
int n, k, i, j, c;
n = strlen(str);
map<string,int> combinationMap;
for( k =1; k<=n; k++)
{
char tempStr[20];
int index =0;
for (i=0; i<(1<<n); i++) {
index =0;
for (j=0,c=0; j<32; j++) if (i & (1<<j)) c++;
if (c == k) {
for (j=0;j<32; j++)
if (i & (1<<j))
tempStr[ index++] = str[j];
tempStr[index] = '\0';
qsort (tempStr, index, sizeof(char), compare);
if( combinationMap.find(tempStr) == combinationMap.end() )
{
// cout<<"comb : "<<tempStr<<endl;
//cout<<"unique comb : \n";
combinationMap[tempStr] = 1;
permute(tempStr,0,k);
} /*
else
{
cout<<"duplicated comb : "<<tempStr<<endl;
}*/
}
}
}
}
int main () {
char str[20];
cin>>str;
generateAllCombinations(str);
cin>>str;
}
I need to use a hash for avoiding same combination, so please let me know how can I make this algorithm better.
Thanks,
GG
#include <algorithm>
#include <iostream>
#include <string>
int main() {
using namespace std;
string s = "abc";
do {
cout << s << '\n';
} while (next_permutation(s.begin(), s.end()));
return 0;
}
Next_permutation uses a constant size, but you can add a loop to deal with varying size. Or just store in a set to eliminate the extra dupes for you:
#include <set>
int main() {
using namespace std;
string s = "abc";
set<string> results;
do {
for (int n = 1; n <= s.size(); ++n) {
results.insert(s.substr(0, n));
}
} while (next_permutation(s.begin(), s.end()));
for (set<string>::const_iterator x = results.begin(); x != results.end(); ++x) {
cout << *x << '\n';
}
return 0;
}
I don't think you can write much faster program than you have already. The main problem is the output size: it has order of n!*2^n (number of subsets * average number of permutations for one subset), which is already > 10^9 for a string of 10 different characters.
Since STL's next_permutation adds very limited complexity for such small strings, your program's time complexity is already nearly O(output size).
But you can make your program a bit simpler. In particular, for( k =1; k<=n; k++) loop seems unnecessary: you already calculate size of subset in variable c inside. So, just have int k = c instead of if (c == k). (You'll also need to consider case of empty subset: i == 0)
edit
Actually, there's only 9864100 outputs for n == 10 (not ~ 10^9). Still, my point remains the same: your program already wastes only "O(next_permutation)" time for each output, which is very, very little.