Improvements for isPrime function - c++

There are many problems on the internet that require you to find prime numbers, so I decided to write a set of functions to find them. I used the Sieve of Eratosthenes for generating the primes as it was fast and easy to implement compared to other algorithms. However, I'm wondering if my code rather than my method is inefficient. Am I using STL containers/iterators right? Is there any section in my code slowing down the program?
In other words it does calculate the results correctly, but what I wonder about is whether its efficiency can be improved by some algorithmic improvement as opposed to just some code tweaking.
Any help is truly appreciated.
Here's my code
(I apologize if it's hard to read)
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define initial_prime_barrier 100
bool isFlagged(int i) { return i == 0; }
bool isNextStart(int i) { return i != 0; }
vector<int> generatePrimesBelow(int limit)
{
vector<int> primes;
for (int i = 2; i < limit; i++)
{
primes.push_back(i);
}
vector<int>::iterator currentStart = primes.begin();
do
{
int numberAtStart = *currentStart;
vector<int>::iterator currentNumber = currentStart + numberAtStart;
do
{
*currentNumber = 0;
advance(currentNumber, numberAtStart);
} while (currentNumber < primes.end());
currentStart = find_if(currentStart + 1, primes.end(), isNextStart);
} while ((*currentStart) * (*currentStart) < limit);
vector<int>::iterator newEnd = remove_if(primes.begin(), primes.end(), isFlagged);
primes.erase(newEnd, primes.end());
return primes;
}
bool isPrime(int number)
{
static vector<int> primes = generatePrimesBelow(initial_prime_barrier);
static int numPrimes = primes.size();
static int largestPrime = primes[numPrimes-1];
static int halfwayPrime = primes[numPrimes/2];
if (number == largestPrime)
{
return true;
}
else if (number < largestPrime)
{
if (number == halfwayPrime)
{
return true;
}
else if (number > halfwayPrime)
{
for (int i = numPrimes/2; i < numPrimes; i++)
{
if (number == primes[i])
{
return true;
}
}
}
else if (number < halfwayPrime)
{
for (int i = numPrimes/2; i >= 0; i--)
{
if (number == primes[i])
{
return true;
}
}
}
}
else if (number > largestPrime)
{
primes = generatePrimesBelow(number + number);
numPrimes = primes.size();
largestPrime = primes[numPrimes-1];
halfwayPrime = primes[numPrimes/2];
return isPrime(number);
}
return false;
}
int main (int argc, char * const argv[])
{
const int number = 123123;
cout << (isPrime(number) ? "YES" : "NO") << endl;
}

Yes, it is your method. Several things. You don't need your array to hold numbers, each entry's address in the array is the number itself. You just need them to hold two values - true and false. So make your array vector<bool>, it will be much more compact. Then, in your inner loop you start from x+x and advance by steps of x. You should start from x*x, and advance by steps of 2*x - that will work for all x except 2. Make it a special case, or mark these even numbers at the initialization loop. Or treat an entry at i as representing the number 2*i+1 and dispense with handling evens altogether. This should speed up your sieve code. Lastly, you don't need special find_if call with all its machinery, you can just check the current entry that comes up in the loop.
(edit:) In your isPrime you perform a binary search by hand, but there is already a binary_search algo in STL. And you won't need it at all, if you keep your vector<bool> sieve array as is, without compressing. Then isPrime(i) needs just to check whether the array's value at the index i is still true.
(edit2:) Now, about efficiency. You recalculate up to n+n, probably in anticipation of more numbers to test. If you only test few, simple trial division on odds will be faster. If the numbers to test are all in a narrow-ish upper region, your best option is offset sieve with the lower sieve done up to the sqrt of the test region's upper limit. And if the numbers are widely distributed, then your current whole array approach can be used.
The key facts to use here is that there are approximately n ~= m/log m primes below m in value, that to sieve an array from 0 to m takes O(m*log (log m)) time, and that to sieve the upper region between a and b, i.e. with width d=b-a, by all the primes below r=sqrt b, it'd take time proportional to d*log (log r).
Also, when growing your sieve array it is best to expand, and not to recalculate the whole anew. The primes are all there. To sieve the appendage it will be necessary to loop through all the primes in the sieve array up to the sqrt of its new upper edge. This is reminiscent of segmented sieve, although there each new segment comes instead of, or in any case separately from a previous one.

Related

Golomb sequence without using array

Hi guys I'm looking for a program to find nth number of Golomb sequence without using array!!!!
**
I know this below program, But it's so so slow...
#include <bits/stdc++.h>
using namespace std;
int findGolomb(int);
int main()
{
int n;
cin >> n;
cout << findGolomb(n);
return 0;
}
int findGolomb(int n)
{
if (n == 1)
return 1;
else
return 1 + findGolomb(n - findGolomb(findGolomb(n - 1)));
}
It depends on how large a value you want to calculate. For n <= 50000, the following works:
#include <cmath>
/*
*/
round(1.201*pow(n, 0.618));
As it turns out, due to the nature of this sequence, you need almost every single entry in it to compute g[n]. I coded up a solution that uses a map to save past calculations, purging it of unneeded values. For n == 500000, the map still had roughly 496000 entries, and since a map has two values where the array would have one, you end up using about twice as much memory.
#include <iostream>
#include <map>
using namespace std;
class Golomb_Generator {
public:
int next() {
if (n == 1)
return cache[n++] = 1;
int firstTerm = n - 1;
int secondTerm = cache[firstTerm];
int thirdTerm = n - cache[secondTerm];
if (n != 3) {
auto itr = cache.upper_bound(secondTerm - 1);
cache.erase(begin(cache), itr);
}
return cache[n++] = 1 + cache[thirdTerm];
}
void printCacheSize() {
cout << cache.size() << endl;
}
private:
int n = 1;
map<int, int> cache;
};
void printGolomb(long long n)
{
Golomb_Generator g{};
for (int i = 0; i < n - 1; ++i)
g.next();
cout << g.next() << endl;
g.printCacheSize();
}
int main()
{
int n = 500000;
printGolomb(n);
return EXIT_SUCCESS;
}
You can guess as much. n - g(g(n - 1)) uses g(n-1) as an an argument to g, which is always much, much smaller than n. At the same time, the recurrence also uses n - 1 as an argument, which is close to n. You can't delete that many entries.
About the best you can do without O(n) memory is recursion combined with the approximation that is accurate for smaller n, but it will still become slow quickly. Additionally, as the recursive calls stack up, you will likely use more memory than having an appropriately sized array would.
You might be able to do a little better though. The sequence grows very slowly. Applying that fact to g(n - g(g(n - 1))), you can convince yourself that this relationship mostly needs stored values nearer to 1 and stored values nearer to n -- nearN(n - near1(nearN(n - 1))). You can have a tremendous swath in between that do not need to be stored, because they would be used in calculations of g(n) for much, much larger n than you care about. Below is an example of maintaining the first 10000 values of g and the last 20000 values of g. It works at least for n <= 2000000, and it stops working for sure at n >= 2500000. For n == 2000000, it takes about 5 to 10 seconds to compute.
#include <iostream>
#include <unordered_map>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
class Golomb_Generator {
public:
int next() {
return g(n++);
}
private:
int n = 1;
map<int, int> higherValues{};
vector<int> lowerValues{1, 1};
int g(int n) {
if(n == 1)
return 1;
if (n <= 10000) {
lowerValues.push_back(1 + lowerValues[n - lowerValues[lowerValues[n - 1]]]);
return higherValues[n] = lowerValues[n];
}
removeOldestResults();
return higherValues[n] = 1 + higherValues[n - lowerValues[higherValues[n - 1]]];
}
void removeOldestResults() {
while(higherValues.size() >= 20000)
higherValues.erase(higherValues.begin());
}
};
void printGolomb(int n)
{
Golomb_Generator g{};
for (int i = 0; i < n - 1; ++i)
g.next();
cout << g.next() << endl;
}
int main()
{
int n = 2000000;
printGolomb(n);
return EXIT_SUCCESS;
}
There are some choices and considerations regarding the runtime.
move the complexity to math
The algorithm actually is nothing else but math in computer language. The algorithm may be improved by mathematical substitutions. You may look into the research regarding this algorithm and may find a better algorithm substitute.
move the complexity to the compiler.
When calling the findGolomb(12) with a specific number known at compile time, we may use constexpr, to move the calculation time to the compiler.
constexpr int findGolomb(int);
move the complexity to the memory
Although requested by the Question to not use an array, this is a considerable constraint. Without using any additional memory space, the algorithm has no options but to use runtime, to for example, to known already computed values of findGolomb(..).
The memory constraint may also include the size of the compiled program (by additional lines of code).
move the complexity to the runtime
When not using math, compiler or memory to enhance the algorithm, there is left no options but to move the complexity to the runtime.
Summarizing, there won't be any options to improve the runtime without the four options above. Removing compiler and memory optimizations, and considering the current runtime as already optimal, you are only left with math and research.

Trouble sieving primes from a large range

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
int t,m,n;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&m,&n);
int rootn=sqrt(double(n));
bool p[10000]; //finding prime numbers from 1 to square_root(n)
for(int j=0;j<=rootn;j++)
p[j]=true;
p[0]=false;
p[1]=false;
int i=rootn;
while(i--)
{
if(p[i]==true)
{
int c=i;
do
{
c=c+i;
p[c]=false;
}while(c+p[i]<=rootn);
}
};
i=0;
bool rangep[10000]; //used for finding prime numbers between m and n by eliminating multiple of primes in between 1 and squareroot(n)
for(int j=0;j<=n-m+1;j++)
rangep[j]=true;
i=rootn;
do
{
if(p[i]==true)
{
for(int j=m;j<=n;j++)
{
if(j%i==0&&j!=i)
rangep[j-m]=false;
}
}
}while(i--);
i=n-m;
do
{
if(rangep[i]==true)
printf("%d\n",i+m);
}while(i--);
printf("\n");
}
return 0;
system("PAUSE");
}
Hello I'm trying to use the sieve of Eratosthenes to find prime numbers in a range between m to n where m>=1 and n<=100000000. When I give input of 1 to 10000, the result is correct. But for a wider range, the stack is overflowed even if I increase the array sizes.
               
A simple and more readable implementation
void Sieve(int n) {
int sqrtn = (int)sqrt((double)n);
std::vector<bool> sieve(n + 1, false);
for (int m = 2; m <= sqrtn; ++m) {
if (!sieve[m]) {
cout << m << " ";
for (int k = m * m; k <= n; k += m)
sieve[k] = true;
}
}
for (int m = sqrtn; m <= n; ++m)
if (!sieve[m])
cout << m << " ";
}
Reason of getting error
You are declaring an enormous array as a local variable. That's why when the stack frame of main is pushed it needs so much memory that stack overflow exception is generated. Visual studio is tricky enough to analyze the code for projected run-time stack usage and generate exception when needed.
Use this compact implementation. Moreover you can have bs declared in the function if you want. Don't make implementations complex.
Implementation
typedef long long ll;
typedef vector<int> vi;
vi primes;
bitset<100000000> bs;
void sieve(ll upperbound) {
_sieve_size = upperbound + 1;
bs.set();
bs[0] = bs[1] = 0;
for (ll i = 2; i <= _sieve_size; i++)
if (bs[i]) { //if not marked
for (ll j = i * i; j <= _sieve_size; j += i) //check all the multiples
bs[j] = 0; // they are surely not prime :-)
primes.push_back((int)i); // this is prime
} }
call from main() sieve(10000);. You have primes list in vector primes.
Note: As mentioned in comment--stackoverflow is quite unexpected error here. You are implementing sieve but it will be more efficient if you use bistet instead of bool.
Few things like if n=10^8 then sqrt(n)=10^4. And your bool array is p[10000]. So there is a chance of accessing array out of bound.
I agree with the other answers,
saying that you should basically just start over. 
Do you even care why your code doesn’t work?  (You didn’t actually ask.)
I’m not sure that the problem in your code
has been identified accurately yet. 
First of all, I’ll add this comment to help set the context:
// For any int aardvark;
// p[aardvark] = false means that aardvark is composite (i.e., not prime).
// p[aardvark] = true means that aardvark might be prime, or maybe we just don’t know yet.
Now let me draw your attention to this code:
int i=rootn;
while(i--)
{
if(p[i]==true)
{
int c=i;
do
{
c=c+i;
p[c]=false;
}while(c+p[i]<=rootn);
}
};
You say that n≤100000000 (although your code doesn’t check that), so,
presumably, rootn≤10000, which is the dimensionality (size) of p[]. 
The above code is saying that, for every integer i
(no matter whether it’s prime or composite),
2×i, 3×i, 4×i, etc., are, by definition, composite. 
So, for c equal to 2×i, 3×i, 4×i, …,
we set p[c]=false because we know that c is composite.
But look closely at the code. 
It sets c=c+i and says p[c]=false
before checking whether c is still in range
to be a valid index into p[]. 
Now, if n≤25000000, then rootn≤5000. 
If i≤ rootn, then i≤5000, and, as long as c≤5000, then c+i≤10000. 
But, if n>25000000, then rootn>5000,†
and the sequence i=rootn;, c=i;, c=c+i;
can set c to a value greater than 10000. 
And then you use that value to index into p[]. 
That’s probably where the stack overflow occurs.
Oh, BTW; you don’t need to say if(p[i]==true); if(p[i]) is good enough.
To add insult to injury, there’s a second error in the same block:
while(c+p[i]<=rootn). 
c and i are ints,
and p is an array of bools, so p[i] is a bool —
and yet you are adding c + p[i]. 
We know from the if that p[i] is true,
which is numerically equal to 1 —
so your loop termination condition is while (c+1<=rootn);
i.e., while c≤rootn-1. 
I think you meant to say while(c+i<=rootn).
Oh, also, why do you have executable code
immediately after an unconditional return statement? 
The system("PAUSE"); statement cannot possibly be reached.
(I’m not saying that those are the only errors;
they are just what jumped out at me.)
______________
† OK, splitting hairs, n has to be ≥ 25010001
(i.e., 50012) before rootn>5000.

C++ algorithm optimization: find K combination from N elements

I am pretty noobie with C++ and am trying to do some HackerRank challenges as a way to work on that.
Right now I am trying to solve Angry Children problem: https://www.hackerrank.com/challenges/angry-children
Basically, it asks to create a program that given a set of N integer, finds the smallest possible "unfairness" for a K-length subset of that set. Unfairness is defined as the difference between the max and min of a K-length subset.
The way I'm going about it now is to find all K-length subsets and calculate their unfairness, keeping track of the smallest unfairness.
I wrote the following C++ program that seems to the problem correctly:
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
int unfairness = -1;
int N, K, minc, maxc, ufair;
int *candies, *subset;
void check() {
ufair = 0;
minc = subset[0];
maxc = subset[0];
for (int i = 0; i < K; i++) {
minc = min(minc,subset[i]);
maxc = max(maxc, subset[i]);
}
ufair = maxc - minc;
if (ufair < unfairness || unfairness == -1) {
unfairness = ufair;
}
}
void process(int subsetSize, int nextIndex) {
if (subsetSize == K) {
check();
} else {
for (int j = nextIndex; j < N; j++) {
subset[subsetSize] = candies[j];
process(subsetSize + 1, j + 1);
}
}
}
int main() {
cin >> N >> K;
candies = new int[N];
subset = new int[K];
for (int i = 0; i < N; i++)
cin >> candies[i];
process(0, 0);
cout << unfairness << endl;
return 0;
}
The problem is that HackerRank requires the program to come up with a solution within 3 seconds and that my program takes longer than that to find the solution for 12/16 of the test cases. For example, one of the test cases has N = 50 and K = 8; the program takes 8 seconds to find the solution on my machine. What can I do to optimize my algorithm? I am not very experienced with C++.
All you have to do is to sort all the numbers in ascending order and then get minimal a[i + K - 1] - a[i] for all i from 0 to N - K inclusively.
That is true, because in optimal subset all numbers are located successively in sorted array.
One suggestion I'd give is to sort the integer list before selecting subsets. This will dramatically reduce the number of subsets you need to examine. In fact, you don't even need to create subsets, simply look at the elements at index i (starting at 0) and i+k, and the lowest difference for all elements at i and i+k [in valid bounds] is your answer. So now instead of n choose k subsets (factorial runtime I believe) you just have to look at ~n subsets (linear runtime) and sorting (nlogn) becomes your bottleneck in performance.

Number prime with c++, what is wrong with the code and how to optimize? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm trying to figure this problem http://www.urionlinejudge.com.br/judge/problems/view/1032, where I need to find the prime numbers between 1 to 3501 the fastest way, since the time limit may not exceed 1 second.
The way I'm calculating these prime numbers is to check if they are prime until their square root, then eliminating the multiple of the first prime numbers [2, 3, 5, 7] to improve the performance of the algorithm. Yet, the time exceeds.
My code (takes 1.560s as the internal testing of the submission system)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <set>
using namespace std;
set<int> circ;
set<int> primes;
/* Calculate List Primes */
void n_prime(int qtd){
int a, flag=1, l_prime = 1;
float n;
for(int i=0;i<qtd;i++){
switch (l_prime){
case 1:
l_prime = 2;
break;
case 2:
l_prime = 3;
break;
default:
while(1){
flag=1;
l_prime+=2;
if(l_prime>7)
while(l_prime%2==0||l_prime%3==0||l_prime%5==0||l_prime%7==0) l_prime++;
n=sqrt(l_prime);
for(a=2;a<=n;a++){
if(l_prime%a==0){
flag=0;
break;
}
}
if(flag) break;
}
}
primes.insert(l_prime);
}
}
/* Initialize set with live's */
void init_circ(int t){
circ.clear();
for(int a=0;a<t;a++){
circ.insert(a+1);
}
}
/* Show last live*/
void show_last(){
for(set<int>::iterator it=circ.begin(); it!=circ.end(); ++it)
cout << *it << "\n";
}
int main(){
int n = 0;
clock_t c1, c2;
c1 = clock();
n_prime(3501);
while(scanf("%d", &n)&&n!=0){
init_circ(n);
int idx=0, l_prime,count = 0;
set<int>::iterator it;
set<int>::iterator np;
np=primes.begin();
for(int i=0;i<n-1;i++){
l_prime=*np;
*np++;
idx = (idx+l_prime-1) % circ.size();
it = circ.begin();
advance(it, idx);
circ.erase(it);
}
show_last();
}
c2 = clock();
printf("\n\nTime: %.3lf", (double)(c2-c1)/CLOCKS_PER_SEC);
return 0;
}
The easiest way is the sieve of Eratosthenes, here's my implementation:
//return the seive of erstothenes
std::vector<int> generate_seive(const ulong & max) {
std::vector<int> seive{2};
std::vector<bool> not_prime(max+1);
ulong current_prime = seive.back();
bool done = false;
while(!done){
for (int i = 2; i * current_prime <= max;i++) {
not_prime[i*current_prime]=true;
}
for (int j = current_prime+1;true;j++) {
if (not_prime[j] == false) {
if( j >= max) {
done = true;
break;
}
else {
seive.push_back(j);
current_prime = j;
break;
}
}
}
}
return seive;
}
Generates all the prime numbers under max, BTW these are the times for my sieve and 3501 as the max number.
real 0m0.008s
user 0m0.002s
sys 0m0.002s
There is a better algorithm for finding primes. Have you heard about Eratosthenes and his sieve?
Also, you are using tons of STL (i.e. the set<>) as well as remainder operations in your code. This is simply killing the speed of your program.
Some basic advice, then a basic (albeit untested) answer...
The advice: If you have one resource that's very limited, take advantage of other resources. In this case, since time is limited, take up a lot of space. Don't dynamically allocate any memory, make it all fixed length arrays.
The way I would do it is simply to have one boolean array and apply Aristophanes' sieve to it:
void findPrimes(int cap) { // set to void for now, since I don't know your return type
bool[] possibilities = new bool[cap + 1]; // has to be dynamic so that you can scale for any top
possibilities[0] = false;
possibilities[1] = false;
int found = 0;
for (int i = 2; i < cap; ) {
++found;
for (int j = i + i; j < cap; j += i) {
possibilities[j] = false;
}
do {
++i;
} while (!possibilities[i]);
}
// at this point, found says how many you've found, and everything in possibilities that is true is a factor. Just return it however you need.
I see aaronman beat me to the punch with the sieve idea. Mine is a slightly different implementation (more exactly resembles the original sieve, using only addition), and uses less dynamic memory, so I'm still submitting it.
You can get quite a nice speedup by preexcluding even numbers, just change your increment to i += 2 and make sure you don't omit 2 in your result array. You might even think about trying to preexclude multiples of 3, but that starts getting dirty. Something along the lines:
for(long i = 1; i < qtd; i += 6) {
//check if i is prime
//check if i+4 is prime
}
This should be enough to get you below the limit.
The sieve of Eratosthenes is the right way to do it, as others have suggested. But the implementations I saw here were very complicated. The sieve is extremely easy to implement. E.g.:
std::vector<int> get_primes(uint max) {
std::vector<int> primes;
std::vector<bool> is_composite(max+1,false);
for (uint i = 2; i <= max; ++i) {
if (!is_composite[i]) {
primes.push_back(i);
for (uint j = i+i; j <= max; j += i) {
is_composite[j] = true;
}
}
}
return primes;
}
There are two big, technical performance drains in your code:
You insert your primes into a vector. Whenever the vector exceeds its allocated size, it will get a new, larger buffer, copy everything over, and delete the old one. new is very expensive in terms of performance, even more expensive than the copying involved. You can avoid this by telling the vector to reserve() enough space.
You use sqrt() in your inner loop. This too is a slow function, square the prime instead (takes only one cycle on modern hardware), it will be faster.

Prime numbers program

I'm currently trying out some questions just to practice my programming skills. ( Not taking it in school or anything yet, self taught ) I came across this problem which required me to read in a number from a given txt file. This number would be N. Now I'm suppose to find the Nth prime number for N <= 10 000. After I find it, I'm suppose to print it out to another txt file. Now for most parts of the question I'm able to understand and devise a method to get N. The problem is that I'm using an array to save previously found prime numbers so as to use them to check against future numbers. Even when my array was size 100, as long as the input integer was roughly < 15, the program crashes.
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
int main() {
ifstream trial;
trial.open("C:\\Users\\User\\Documents\\trial.txt");
int prime;
trial >> prime;
ofstream write;
write.open("C:\\Users\\User\\Documents\\answer.txt");
int num[100], b, c, e;
bool check;
b = 0;
switch (prime) {
case 1:
{
write << 2 << endl;
break;
}
case 2:
{
write << 3 << endl;
break;
}
case 3:
{
write << 5 << endl;
break;
}
case 4:
{
write << 7 << endl;
break;
}
default:
{
for (int a = 10; a <= 1000000; a++) {
check = false;
if (((a % 2) != 0) && ((a % 3) != 0) && ((a % 5) != 0) && ((a % 7) != 0)) // first filter
{
for (int d = 0; d <= b; d++) {
c = num[d];
if ((a % c) == 0) {
check = true; // second filter based on previous recorded primes in array
break;
}
}
if (!check) {
e = a;
if (b <= 100) {
num[b] = a;
}
b = b + 1;
}
}
if ((b) == (prime - 4)) {
write << e << endl;
break;
}
}
}
}
trial.close();
write.close();
return 0;
}
I did this entirely base on my dummies guide and myself so do forgive some code inefficiency and general newbie-ness of my algorithm.
Also for up to 15 it displays the prime numbers correctly.
Could anyone tell me how I should go about improving this current code? I'm thinking of using a txt file in place of the array. Is that possible? Any help is appreciated.
Since your question is about programming rather than math, I will try to keep my answer that way too.
The first glance of your code makes me wonder what on earth you are doing here... If you read the answers, you will realize that some of them didn't bother to understand your code, and some just dump your code to a debugger and see what's going on. Is it that we are that impatient? Or is it simply that your code is too difficult to understand for a relatively easy problem?
To improve your code, try ask yourself some questions:
What are a, b, c, etc? Wouldn't it better to give more meaningful names?
What exactly is your algorithm? Can you write down a clearly written paragraph in English about what you are doing (in an exact way)? Can you modify the paragraph into a series of steps that you can mentally carry out on any input and can be sure that it is correct?
Are all steps necessary? Can we combine or even eliminate some of them?
What are the steps that are easy to express in English but require, say, more than 10 lines in C/C++?
Does your list of steps have any structures? Loops? Big (probably repeated) chunks that can be put as a single step with sub-steps?
After you have going through the questions, you will probably have a clearly laid out pseudo-code that solves the problem, which is easy to explain and understand. After that you can implement your pseudo-code in C/C++, or, in fact, any general purpose language.
There are a two approaches to testing for primality you might want to consider:
The problem domain is small enough that just looping over the numbers until you find the Nth prime would probably be an acceptable solution and take less than a few milliseconds to complete. There are a number of simple optimizations you can make to this approach for example you only need to test to see if it's divisible by 2 once and then you only have to check against the odd numbers and you only have to check numbers less than or equal to the aquare root of the number being tested.
The Sieve of Eratosthenes is very effective and easy to implement and incredibly light on the math end of things.
As for why you code is crashing I suspect changing the line that reads
for( int d=0; d<=b; d++)
to
for( int d=0; d<b; d++)
will fix the problem because you are trying to read from a potentially uninitialized element of the array which probably contains garbage.
I haven't looked at your code, but your array must be large enough to contain all the values you will store in it. 100 certainly isn't going to be enough for most input for this problem.
E.g. this code..
int someArray[100];
someArray[150] = 10;
Writes to a location large than the array (150 > 100). This is known as a memory overwrite. Depending on what happened to be at that memory location your program may crash immediately, later, or never at all.
A good practice when using arrays is to assert in someway that the element you are writing to is within the bounds of the array. Or use an array-type class that performs this checking.
For your problem the easiest approach would be to use the STL vector class. While you must add elements (vector::push_back()) you can later access elements using the array operator []. Vector will also give you the best iterative performance.
Here's some sample code of adding the numbers 0-100 to a vector and then printing them. Note in the second loop we use the count of items stored in the vector.
#include <vector> // std::vector
...
const int MAX_ITEMS = 100;
std::vector<int> intVector;
intVector.reserve(MAX_ITEMS); // allocates all memory up-front
// add items
for (int i = 0; i < MAX_ITEMS; i++)
{
intVector.push_back(i); // this is how you add a value to a vector;
}
// print them
for (int i = 0; i < intVector.size(); i++)
{
int elem = intVector[i]; // this access the item at index 'i'
printf("element %d is %d\n", i, elem);
}
I'm trying to improve my functional programming at the moment so I just coded up the sieve quickly. I figure I'll post it here. If you're still learning, you might find it interesting, too.
#include <iostream>
#include <list>
#include <math.h>
#include <functional>
#include <algorithm>
using namespace std;
class is_multiple : public binary_function<int, int, bool>
{
public:
bool operator()(int value, int test) const
{
if(value == test) // do not remove the first value
return false;
else
return (value % test) == 0;
}
};
int main()
{
list<int> numbersToTest;
int input = 500;
// add all numbers to list
for(int x = 1; x < input; x++)
numbersToTest.push_back(x);
// starting at 2 go through the list and remove all multiples until you reach the squareroot
// of the last element in the list
for(list<int>::iterator itr = ++numbersToTest.begin(); *itr < sqrt((float) input); itr++)
{
int tmp = *itr;
numbersToTest.remove_if(bind2nd(is_multiple(), *itr));
itr = find(numbersToTest.begin(), numbersToTest.end(), tmp); //remove_if invalidates iterator
// so find it again. kind of ugly
}
// output primes
for(list<int>::iterator itr = numbersToTest.begin(); itr != --numbersToTest.end(); itr++)
cout << *itr << "\t";
system("PAUSE");
return 0;
}
Any advice on how to improve this would be welcome by the way.
Here is my code. When working on a big number, it's very slow!
It can calculate all prime numbers with in the number you input!
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
int main()
{
int m;
int n=0;
char ch;
fstream fp;
cout<<"What prime numbers do you want get within? ";
if((cin>>m)==0)
{
cout<<"Bad input! Please try again!\n";
return 1;
}
if(m<2)
{
cout<<"There are no prime numbers within "<<m<<endl;
return 0;
}
else if(m==2)
{
fp.open("prime.txt",ios::in|ios::out|ios::trunc);//create a file can be writen and read. If the file exist, it will be overwriten.
fp<<"There are only 1 prime number within 2.\n";
fp<<"2\n";
fp.close();
cout<<"Congratulations! It has worked out!\n";
return 0;
}
else
{
int j;
int sq;
fp.open("prime.txt",ios::in|ios::out|ios::trunc);
fp<<"2\t\t";
n++;
for(int i=3;i<=m;i+=2)
{
sq=static_cast<int>(sqrt(i))+1;
fp.seekg(0,ios::beg);
fp>>j;
for(;j<sq;)
{
if(i%j==0)
{
break;
}
else
{
if((fp>>j)==NULL)
{
j=3;
}
}
}
if(j>=sq)
{
fp.seekg(0,ios::end);
fp<<i<<"\t\t";
n++;
if(n%4==0)
fp<<'\n';
}
}
fp.seekg(0,ios::end);
fp<<"\nThere are "<<n<<" prime number within "<<m<<".\n";
fp.close();
cout<<"Congratulations! It has worked out!\n";
return 0;
}
}
For one, you'd have less code (which is always a good thing!) if you didn't have special cases for 3, 5 and 7.
Also, you can avoid the special case for 2 if you just set num[b] = 2 and only test for divisibility by things in your array.
It looks like as you go around the main for() loop, the value of b increases.
Then, this results in a crash because you access memory off the end of your array:
for (int d = 0; d <= b; d++) {
c = num[d];
I think you need to get the algorithm clearer in your head and then approach the code again.
Running your code through a debugger, I've found that it crashes with a floating point exception at "if ((a % c) == 0)". The reason for this is that you haven't initialized anything in num, so you're doing "a % 0".
From what I know, in C/C++ int is a 16bit type so you cannot fit 1 million in it (limit is 2^16=32k). Try and declare "a" as long
I think the C standard says that int is at least as large as short and at most as large as long.
In practice int is 4 bytes, so it can hold numbers between -2^31 and 2^31-1.
Since this is for pedagogical purposes, I would suggest implementing the Sieve of Eratosthenes.
This should also be of interest to you: http://en.wikipedia.org/wiki/Primality_test
for(int currentInt=2; currentInt<=1000000; currentInt++)
{check = false; // Basically the idea for this for loop is to run checks against integers. This is the main for loop in this program. I re initialize check to false ( check is a bool declared above this. )
for( int arrayPrime=0; arrayPrime<currentPrime; arrayPrime++) // This for loop is used for checking the currentInt against previously found primes which are stored in the num array.
{ c=num[arrayPrime];
if ((currentInt%c)==0) { check = true;// second filter based on previous recorded primes in array
break;} // this is the check. I check the number against every stored value in the num array. If it's divisible by any of them, then bool check is set to true.
if ( currentInt == 2)
{ check = false; } // since i preset num[0] = 2 i make an exception for the number 2.
if (!check)
{
e=a;
if(currentPrime <= 100){
num[currentPrime]= currentInt;} // This if uses check to see if the currentInt is a prime.
currentPrime = currentPrime+1;} // increases the value of currentPrime ( previously b ) by one if !check.
if(currentPrime==prime)
{
write<<e<<endl;
break;} // if currentPrime == prime then write the currentInt into a txt file and break loop, ending the program.
Thanks for the advice polythinker =)
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
int main()
{
ifstream trial;
trial.open("C:\\Users\\User\\Documents\\trial.txt");
int prime, e;
trial>>prime;
ofstream write;
write.open("C:\\Users\\User\\Documents\\answer.txt");
int num[10000], currentPrime, c, primePrint;
bool check;
currentPrime=0;
num[currentPrime] = 2;
currentPrime=1;
for(int currentInt=2; currentInt<=1000000; currentInt++)
{check = false;
for( int arrayPrime=0; arrayPrime<currentPrime; arrayPrime++)
{ c=num[arrayPrime];
if ((currentInt%c)==0) { check = true;// second filter based on previous recorded primes in array
break;}
}
if (!check)
{ e=currentInt;
if( currentInt!= 2 ) {
num[currentPrime]= currentInt;}
currentPrime = currentPrime+1;}
if(currentPrime==prime)
{
write<<e<<endl;
break;}
}
trial.close();
write.close();
return 0;
}
This is the finalized version base on my original code. It works perfectly and if you want to increase the range of prime numbers simply increase the array number. Thanks for the help =)
Since you will need larger prime number values for later questions, I suggest you follow dreeves advice, and do a sieve. It is a very useful arrow to have in your quiver.