Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
Working on a project Euler problem (#10), I've an interesting compile error. My compiler tells me I need a semicolon. The exact error is 49: ';' expected.
Now I know this is not unusual with C code, but the problem is I've triple checked all semicolons and parentheses and brackets, and none are missing. Not even in loops. Chances are I'm just missing it.
HOWEVER
The compiler tells me 49: ';' expected - but the code on line 49 is just one bracket ({).
Would anyone have any insight into what might be wrong here?
Code is as follows:
// this is a program to find the sum of all primes below 2 million
// uses the Seive of Eratosthenes
#include <stdio.h>
int main() {
long int sum = 0;
long int s = 2000000; // size of array
long int i; // 'for' loops
long int n; // number to test
long int a; // prime checker
long int multiples;
long int* array; // define pointer for calloc int array
// calloc the array
array = (int*)calloc(s, sizeof(int)); // allocates 2,000,000 spots (s) of
// size "int" to array "array"
// set all array values equal to 1
for (i = 0; i < 2000000; i++) {
array[i] = 1;
}
/*
VALUES IN ARRAY
The values of the array indicates whether number-
(0) IS PRIME
(1) UNTESTED
(2) IS COMPOSITE
*/
// implement prime finder
for (n = 0; n < 2000000; n++) {
if (array[n] == 0) // IF n IS PRIME
{
multiples = n;
multiples += n;
while (multiples < 2000000) {
array[multiples] = 2;
multiples += n;
}
} else
(array[n] == 2) // IF n IS COMPOSITE (is a multiple)
{ // THIS IS LINE 49
continue;
}
else(array[n] == 1) // UNTESTED
{
for (a = 2; a < n; a++) // double checks for composites
{
// tests factors
if (n % a == 0) {
printf("ERROR");
goto end;
}
}
array[n] = 0;
multiples = n;
multiples += n;
while (multiples < 2000000) {
array[multiples] = 2;
multiples += n;
}
}
}
// read array and sum primes
for (n = 0; n < 2000000; n++) {
if (array[n] == 0) // IF n IS PRIME
{
sum += n;
} else
(array[n] == 2) // IF n IS COMPOSITE
{
continue;
}
else(array[n] == 1) // IF n MAY/MAY NOT BE PRIME
{
printf("ERROR");
goto end;
}
}
printf("The sum of all primes < 2,000,000 is... %ld!\n", sum);
end:
getchar();
return 0;
}
Change the else to else if and you are fine.
And do that with all the else.
else( array[n] == 2) // IF n IS COMPOSITE (is a multiple)
{ //THIS IS LINE 49
else doesn't take a condition. The else should be else if.
The compiler's syntax recovery tries to suggest the simplest change that would result in a syntactically valid program. Often the suggested change doesn't make much sense. In this case, adding a ; after the else would turn the following ( array[n] == 2) into the beginning of an expression statement (which would have to be followed by another semicolon).
If your code produces a syntax error message, the best approach is often to ignore the suggestion it makes and just look at the line it refers to and the line(s) preceding it, and figure out what's wrong with the syntax at that point. Then fix the error and recompile.
You're really missing is some ifs to go with your elses:
if( array[n] == 0) // IF n IS PRIME
{
sum += n;
}
else if( array[n] == 2) // IF n IS COMPOSITE
{
continue;
}
else if( array[n] == 1) // IF n MAY/MAY NOT BE PRIME
{
printf("ERROR");
goto end;
}
It's pretty easy to confuse a compiler like this, and when you do, some of its error messages can get hard to understand.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
So I am running into an issue that I can't seem to fix. I want to display the factor and the power that it is raised to(basically prime factor decomposition), I had done this in python but for some reason I can't implement this in C and this is what I came up with
#include<stdio.h>
#include<math.h>
int main()
{
int i = 2, p, c, n;
scanf("%d", n);
while (n > 9)
{
p = 0;
c = 1;
while (n % i == 0)
{
for (int d = 2; d <= i / 2 + 1; d++)
if (i % d == 0 && i % 2 != 0)
c = 0;
if (c == 1)
{
p = p + 1;
n = n / i;
}
if (p != 0)
{
printf("%d %d", i, p);
printf("\n");
}
i = i + 1;
}
}
return 0;
}
Problem #1 (although it's not your main problem) is that you're missing a pointer in your scanf call:
scanf("%d", n);
That needs to be
scanf("%d", &n);
(My compiler warned me about this right away. Not sure why yours didn't.)
Problem #2 is that while (n > 9) is just totally wrong. I think you want while (n > 1).
Problem #3 is that the i = i + 1 step is misplaced. You need to do that whether or not i was a factor, so it needs to be at the end of the outermost loop.
And then problem #4 is the code that starts with
for (int d = 2; d <= i / 2 + 1; d++)
It looks like you're trying to check whether i is prime, although you're doing it too late: you're already inside the if where you test whether i is a factor of n. Also you don't have a proper loop to count how many times i is a factor of n.
It turns out, though, that you don't actually need to test whether i is prime, so let's leave the primality-testing step out for a moment and see what happens.
Here's the first fixed version:
#include <stdio.h>
int main()
{
int i = 2, p, n;
scanf("%d", &n);
while (n > 1)
{
if (n % i == 0) /* if i is a factor */
{
p = 0;
while (n % i == 0) /* count how many times i is a factor */
{
n /= i;
p++;
}
printf("%d %d\n", i, p);
}
i++;
}
return 0;
}
And this works! It tries every possible value of i, which is pretty inefficient, but due to the properties of prime factorization, it's okay. It tries them in order, so it will always have weeded out all lower prime factors first, so none of the non-prime i's will make it through to get printed as a factor.
To do what I guess you were trying to do, we have to rearrange the code. The basic algorithm is: for each i, if it's prime, see how many times it divides the running n.
#include <stdio.h>
int main()
{
int i = 2, p, c, n;
scanf("%d", &n);
while (n > 1)
{
/* see if i is prime */
c = 1;
for (int d = 2; d <= i / 2 + 1; d++)
if (i % d == 0 && i % 2 != 0)
{
c = 0;
break;
}
if (c == 1) /* if i is prime */
{
p = 0;
while (n % i == 0) /* count how many times i is a factor */
{
p = p + 1;
n = n / i;
}
if (p != 0)
printf("%d %d\n", i, p);
}
i = i + 1;
}
return 0;
}
The primality test is still pretty crude (that line if (i % d == 0 && i % 2 != 0) is fishy), but it seems to work. I suspect it's still wasteful, though: if you're generating all possible trial divisors to factorize n, there's probably a better way than running a full primality test on each i, from scratch.
One popular shortcut is to have i run through 2,3,5,7,9,11,13,... (that is, 2 plus all the odd numbers). Building on that idea, I once wrote some code that uses a more complicated sequence of increments so that it ends up using 2, 3, 5, and then every odd number that isn't a multiple of 3 or 5. I suspect (but I haven't measured) that wastefully using some number of non-prime trial divisors i might end up being less wasteful than positively confirming that each trial divisor is strictly prime.
But if you really care about efficiency, you'll have to abandon this obvious but still rather brute-force technique of blindly trying all the trial divisors, and move to something more sophisticated like elliptic curve factorization. What we're doing here is trial division, which as Wikipedia notes is "the most laborious but easiest to understand of the integer factorization algorithms".
I am trying to generate a list of all the prime numbers for the first 1000 numbers.
I am not sure where I am going wrong in my code. From what I can tell, my nested for loop is not reading dividing/reading the array correctly and then assigning that array the proper value. How can I fix it?
The program currently only generates all the odd numbers.
int main() {
int x = 1;
int arr[500];
int i, j, k;
int counter;
int primearray[500];
for (j = 0; j <= 500; j++) {
x += 2;
arr[j] = x;
for (k = 1; k <= 15; k++) {
counter = x % k;
if (counter == 0) {
primearray[j] = x;
} else {
break;
}
}
for (i = 0; i < 500; i++) {
printf("%d ", primearray[i]);
}
}
Please invest time in learning how to indent your code. Choose a style that suits you and use it consistently: this will make your programs easier to read, and in turn easier to understand.
As I'm writing this, your posted code doesn't even compile because a closing curly brace } is missing: such editing mistakes are made possible by misleading indentation. Also note that in a properly written C program you must remember to #include any standard headers that are used:
#include <stdio.h> // for `printf()`
Rather than try to fix your algorithm, which at first glance doesn't make any sense to me anyway, I will try to help you restructure your program.
Keep main() simple
Given that the goal of your program is checking which of the first 1000 natural numbers are prime, the main() function should do no more than loop through those numbers and print the ones which are prime, like this:
for (int n=0; n < 1000; ++n)
if (is_prime(n))
printf("%d\n", n);
Putting them in an array instead of printing is equally easy:
int prime_array[500]; // array of primes
int k=0; // current index in array of primes
for (int n=0; n < 1000; ++n)
if (is_prime(n))
prime_array[k++] = n;
Break up the program in several functions
In accordance to the previous idea, write short and simple functions that do one thing, and do it well. In your case, you should write the is_prime() function to determine if a number is prime or not. You can start from here:
///
/// #brief Checks if a number is prime.
/// #param [in] n Number to be checked
/// #returns Whether `n` is prime or not.
/// #retval 1 If `n` is prime.
/// #retval 0 If `n` is not prime.
///
int is_prime(int n)
{
// TODO: add code here
}
Decide how to check for primality
There is a Primality test article on Wikipedia that you should read.
First, you must correctly handle these special cases:
0 is not prime
1 is not prime
2 is prime
// TODO: also check 1 and 2 in a similar fashion
if (n == 0)
return 0;
After this is done, you can use a naive and inefficient algorithm that checks the other numbers:
// try divisors from 2 to n-1
for (int d=2; d < n; ++d)
if (n % d == 0) // if the division was even,
return 0; // the number is not prime
return 1; // if we get here, the number is prime
If you want to use a faster (but more complicated) algorithm for checking primes, look back at the Wikipedia article linked above. Notice how you'd only have to change the code inside is_prime() and the rest of the program would work the same, unchanged.
As I understood from your code, arr is an array of possible candidates and primearray is an array of approved ones. No every candidate will be approved one so you need different variables for indexing them.
The second issue is the algorithm for approving candidates. From this part of your code (I changed some indents)
for (k = 1; k <= 15; k++) {
counter = x%k;
if (counter == 0) {
primearray[j] = x;
} else {
break;
}
follows that you approve a candidate if it is divisible by all integers from 1 to 15 - I am sorry but prime numbers have not this property.
I think you could refer to this code which will generate all prime numbers up to the number that you specify. I think this will be more optimised.
void main()
{
int n, i, j, temp=0;
printf("Enter a number \n");
scanf("%d", &n);
printf(" Prime numbers -\n");
for(i=2; i<n+1; i++)
{
temp = 0;
for(j=2; j<i; j++)
{
if(i%j == 0)
{
temp = 1;
break;
}
}
if(temp == 0)
{
printf("%d \n", i);
}
}
getch();
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
#include <stdio.h>
int main()
{
int i, n, c, p;
printf("enter\n");
scanf("%d", n);
c = find(n);
if (c == 1)
{
printf("no. is not prime");
}
else
{
printf("no. is prime");
}
}
find(int n)
{
int i = 2, p;
while (i < n)
{
p = n % i;
printf("value of p%d", p);
if (p == 0)
{
return 1;
}
i = i + 1;
}
return 2;
}
....................................
Above program giving me 'not a prime number' output for all inputs...also the value of p is always zero and this shouldn't be the case...
Please help...badly stuck...
Your scanf() call must take the address of n. Furthermore you primality test fails for numbers smaller than 2. It is also better to return non-zero for true, zero otherwise, so that the value can directly be tested with if. And you should find a better name than find.
Try something like this:
#define TRUE 1
#define FALSE 0
int is_prime (int n)
{
int i;
if (n < 2)
return FALSE;
for (i = 2; i < n; i++) {
if (n % i == 0) {
return FALSE;
}
}
return TRUE;
}
int main()
{
int n;
printf ("enter number: ");
scanf ("%d", &n);
if (is_prime (n)) {
printf ("number is prime.\n");
}
else {
printf("number is not prime.\n");
}
return 0;
}
Various improvements are possible but I wanted to stay as close to your code as possible.
This looks like a student exercise so let me start by suggesting that the debugger is your friend. :)
Having said that, you may want to review the Sieve of Eratosthenes and leverage Wikipedia for a source of some good test content.
As already suggested, there are loads of potential improvements... I'd modify your "find" function to be more clear as follows:
bool IsPrime(unsigned int n)
{
unsigned int nCounter = 2;
while (n % nCounter++);
return (nCounter > n);
}
Prime's can't be negative and since you're asking a "TRUE/FALSE" question, the name and return type should enforce that contract.
Several issues:
scanf("%d", n); should be scanf("%d", &n); - you need to pass the address of n so scanf can update it (note that you risk a runtime error,
since the value of n most likely isn't a valid address value);
Implicit typing of functions such as find(int n) {...} is no longer supported as of the C99 standard, and it was never good practice to begin with. You should (and for C99 and later, must) provide a type specifier along with the function name in both function declarations and function definitions - int find( int n ) {...};
Similar to 2, a function declaration must be visible before a function is called; the simplest way to accomplish this is to move the function definition above the definition for main. If you don't want to do that, then you need to add the declaration int find(int n); somewhere before find is called.
Note that you can speed up the primality test in a couple of ways. First, you can skip testing against even factors; if a number is divisible by a multiple of 2, then it's divisible by 2, and you would have already checked for that. Secondly, you don't need to test all factors up to n - 1; you only need to test factors up to the square root of n. You can put that all together like so:
if ( n < 2 )
return 0; // zero indicates false
if ( n == 2 )
return 1; // non-zero indicates true
int result = n % 2;
for ( int i = 3; result && i * i <= n; i += 2 ) // loops as long as result
result = n % i; // is non-zero, only tests
// against odd numbers up to
return result; // sqrt(n)
Well, there are lots of such questions available in SO as well as other forums. However, none of these helped.
I wrote a program in "C" to find number of primes within a range. The range i in long int. I am using Sieve of Eratosthenes" algorithm. I am using an array of long ints to store all the numbers from 1 till the limit. I could not think of a better approach to achieve without using an array. The code works fine, till 10000000. But after that, it runs out of memory and exits. Below is my code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef unsigned long uint_32;
int main() {
uint_32 i, N, *list, cross=0, j=4, k, primes_cnt = 0;
clock_t start, end;
double exec_time;
system("cls");
printf("Enter N\n");
scanf("%lu", &N);
list = (uint_32 *) malloc( (N+1) * sizeof(uint_32));
start = clock();
for(i=0; i<=N+1; i++) {
list[i] = i;
}
for(i=0; cross<=N/2; i++) {
if(i == 0)
cross = 2;
else if(i == 1)
cross = 3;
else {
for(j=cross+1; j<=N; j++) {
if(list[j] != 0){
cross = list[j];
break;
}
}
}
for(k=cross*2; k<=N; k+=cross) {
if(k <= N)
list[k] = 0;
}
}
for(i=2; i<=N; i++) {
if(list[i] == 0)
continue;
else
primes_cnt++;
}
printf("%lu", primes_cnt);
end = clock();
exec_time = (double) (end-start);
printf("\n%f", exec_time);
return 0;
}
I am stuck and can't think of a better way to achieve this. Any help will be hugely appreciated. Thanks.
Edit:
My aim is to generate and print all prime numbers below the range. As printing consumed a lot of time, I thought of getting the first step right.
There are other algorithm that does not require you to generate prime number up to N to count number of prime below N. The easiest algorithm to implement is Legendre Prime Counting. The algorithm requires you to generate only sqrt(N) prime to determine the number of prime below N.
The idea behind the algorithm is that
pi(n) = phi(n, sqrt(n)) + pi(sqrt(n)) - 1
where
pi(n) = number of prime below N
phi(n, m) = number of number below N that is not divisible by any prime below m.
That's mean phi(n, sqrt(n)) = number of prime between sqrt(n) to n. For how to calculate the phi, you can go to the following link (Feasible implementation of a Prime Counting Function)
The reason why it is more efficient is because it is easiest to compute phi(n, m) than to compute pi(n). Let say that I want to compute phi(100, 3) means that how many number below or equal to 100 that does not divisible by 2 and 3. You can do as following. phi(100, 3) = 100 - 100/2 - 100/3 + 100/6.
Your code uses about 32 times as much memory as it needs. Note that since you initialized list[i] = i the assignment cross = list[j] can be replaced with cross = j, making it possible to replace list with a bit vector.
However, this is not enough to bring the range to 264, because your implementation would require 261 bytes (2 exbibytes) of memory, so you need to optimize some more.
The next thing to notice is that you do not need to go up to N/2 when "crossing" the numbers: √N is sufficient (you should be able to prove this by thinking about the result of dividing a composite number by its divisors above √N). This brings memory requirements within your reach, because your "crossing" primes would fit in about 4 GB of memory.
Once you have an array of crossing primes, you can build a partial sieve for any range without keeping in memory all ranges that precede it. This is called the Segmented sieve. You can find details on it, along with a simple implementation, on the page of primesieve generator. Another advantage of this approach is that you can parallelize it, bringing the time down even further.
You can tweak the algorithm a bit to calculate the prime numbers in chunks.
Load a part of the array (as much as fits the memory), and in addition hold a list of all known prime numbers.
Whenever you load a chunk, first go through the already known prime numbers, and similar to the regular sieve, set all non primes as such.
Then, go over the array again, mark whatever you can, and add to the list the new prime numbers found.
When done, you'll have a list containing all your prime numbers.
I could see that the approach you are using is the basic implementation of Eratosthenes, that first stick out all the 2's multiple and then 3's multiple and so on.
But I have a better solution to the question. Actually, there is question on spoj PRINT. Please go through it and do check the constraints it follows. Below is my code snippet for this problem:
#include<stdio.h>
#include<math.h>
#include<cstdlib>
int num[46500] = {0},prime[5000],prime_index = -1;
int main() {
/* First, calculate the prime up-to the sqrt(N) (preferably greater than, but near to
sqrt(N) */
prime[++prime_index] = 2; int i,j,k;
for(i=3; i<216; i += 2) {
if(num[i] == 0) {
prime[++prime_index] = i;
for(j = i*i, k = 2*i; j<=46500; j += k) {
num[j] = 1;
}
}
}
for(; i<=46500; i+= 2) {
if(num[i] == 0) {
prime[++prime_index] = i;
}
}
int t; // Stands for number of test cases
scanf("%i",&t);
while(t--) {
bool arr[1000005] = {0}; int m,n,j,k;
scanf("%i%i",&m,&n);
if(m == 1)
m++;
if(m == 2 && m <= n) {
printf("2\n");
}
int sqt = sqrt(n) + 1;
for(i=0; i<=prime_index; i++) {
if(prime[i] > sqt) {
sqt = i;
break;
}
}
for(; m<=n && m <= prime[prime_index]; m++) {
if(m&1 && num[m] == 0) {
printf("%i\n",m);
}
}
if(m%2 == 0) {
m++;
}
for(i=1; i<=sqt; i++) {
j = (m%prime[i]) ? (m + prime[i] - m%prime[i]) : (m);
for(k=j; k<=n; k += prime[i]) {
arr[k-m] = 1;
}
}
for(i=0; i<=n-m; i += 2) {
if(!arr[i]) {
printf("%i\n",m+i);
}
}
printf("\n");
}
return 0;
}
I hope you got the point:
And, as you mentioned that your program is working fine up-to 10^7 but above it fails, it must be because you must be running out of the memory.
NOTE: I'm sharing my code only for knowledge purpose. Please, don't copy and paste it, until you get the point.
I've been interested in the problem of finding a better prime number recognizer for years. I realize this is a huge area of academic research and study - my interest in this is really just for fun. Here was my first attempt at a possible solution, in C (below).
My question is, can you suggest an improvement (without citing some other reference on the net, I'm looking for actual C code)? What I'm trying to get from this is a better understanding of determining performance complexity of a solution like this.
Am I right in concluding that the complexity of this solution is O(n^2)?
#include <stdio.h>
#include <math.h>
/* isprime */
/* Test if each number in the list from stdin is prime. */
/* Output will only print the prime numbers in the list. */
int main(int argc, char* argv[]) {
int returnValue = 0;
int i;
int ceiling;
int input = 0;
int factorFound = 0;
while (scanf("%d", &input) != EOF) {
ceiling = (int)sqrt(input);
if (input == 1) {
factorFound = 1;
}
for (i = 2; i <= ceiling; i++) {
if (input % i == 0) {
factorFound = 1;
}
}
if (factorFound == 0) {
printf("%d\n", input);
}
factorFound = 0;
}
return returnValue;
}
for (i = 2; i <= ceiling; i++) {
if (input % i == 0) {
factorFound = 1;
break;
}
}
This is the first improvement to make and still stay within the bounds of "same" algorithm. It doesn't require any math at all to see this one.
Beyond that, once you see that input is not divisible by 2, there is no need to check for 4, 6, 8, etc. If any even number divided into input, then surely 2 would have because it divides all even numbers.
If you want to step outside of the algorithm a little bit, you could use a loop like the one that Sheldon L. Cooper provides in his answer. (This is just easier than having him correct my code from the comments though his efforts are much appreciated)
this takes advantage of the fact that every prime other than 2 and 3 is of the form n*6 + 1 or n*6 - 1 for some positive integer n. To see this, just note that if m = n*6 + 2 or m = n*6 + 4, then n is divisible by 2. if m = n*6 + 3 then it is divisible by 3.
In fact, we can take this further. If p1, p2, .., pk are the first k primes, then all of the integers that are coprime to their product mark out 'slots' that all remaining primes must fit into.
to see this, just let k# be the product of all primes up to pk. then if gcd(k#, m) = g, g divides n*k# + m and so this sum is trivially composite if g != 1. so if you wanted to iterate in terms of 5# = 30, then your coprime integers are 1, 7, 11, 13, 17, 19, 23 and 29.
technically, I didn't prove my last claim. It's not much more difficult
if g = gcd(k#, m), then for any integer, n, g divides n*k# + m because it divides k# so it must also divide n*k#. But it divides m as well so it must divide the sum. Above I only proved it for n = 1. my bad.
Also, I should note that none of this is changing the fundamental complexity of the algoritm, it will still be O(n^1/2). All it is doing is drastically reducing the coefficient that gets used to calculate actual expected run times.
The time complexity for each primality test in your algorithm is O(sqrt(n)).
You can always use the fact that all primes except 2 and 3 are of the form: 6*k+1 or 6*k-1. For example:
int is_prime(int n) {
if (n <= 1) return 0;
if (n == 2 || n == 3) return 1;
if (n % 2 == 0 || n % 3 == 0) return 0;
int k;
for (k = 6; (k-1)*(k-1) <= n; k += 6) {
if (n % (k-1) == 0 || n % (k+1) == 0) return 0;
}
return 1;
}
This optimization does not improve the asymptotic complexity.
EDIT
Given that in your code you are testing numbers repeatedly, you might want to pre-calculate a list of primes. There are only 4792 primes less than or equal to the square root of INT_MAX (assuming 32 bit ints).
Furthermore, if the input numbers are relatively small you can try calculating a sieve.
Here's a combination of both ideas:
#define UPPER_BOUND 46340 /* floor(sqrt(INT_MAX)) */
#define PRIME_COUNT 4792 /* number of primes <= UPPER_BOUND */
int prime[PRIME_COUNT];
int is_prime_aux[UPPER_BOUND];
void fill_primes() {
int p, m, c = 0;
for (p = 2; p < UPPER_BOUND; p++)
is_prime_aux[p] = 1;
for (p = 2; p < UPPER_BOUND; p++) {
if (is_prime_aux[p]) {
prime[c++] = p;
for (m = p*p; m < UPPER_BOUND; m += p)
is_prime_aux[m] = 0;
}
}
}
int is_prime(int n) {
if (n <= 1) return 0;
if (n < UPPER_BOUND) return is_prime_aux[n];
int i;
for (i = 0; i < PRIME_COUNT && prime[i]*prime[i] <= n; i++)
if (n % prime[i] == 0)
return 0;
return 1;
}
Call fill_primes at the beginning of your program, before starting to process queries. It runs pretty fast.
Your code there only has complexity O(sqrt(n)lg(n)). If you assume basic mathematical operations are O(1) (true until you start using bignums), then it's just O(sqrt(n)).
Note that primality testing can be performed in faster-than-O(sqrt(n)lg(n)) time. This site has a number of implementations of the AKS primality test, which has been proven to operate in O((log n)^12) time.
There are also some very, very fast probalistic tests - while fast, they sometimes give an incorrect result. For example, the Fermat primality test:
Given a number p we want to test for primality, pick a random number a, and test whether a^(p-1) mod p = 1. If false, p is definitely not prime. If true, p is probably prime. By repeating the test with different random values of a, the probability of a false positive can be reduced.
Note that this specific test has some flaws to it - see the Wikipedia page for details, and other probabilistic primality tests you can use.
If you want to stick with the current approach, there are a number of minor improvements which can still be made - as others have pointed out, after 2, all further primes are odd, so you can skip two potential factors at a time in the loop. You can also break out immediately when you find a factor. However, this doesn't change the asymptotic worst-case behavior of your algorithm, which remains at O(sqrt(n)lg(n)) - it just changes the best case (to O(lg(n))), and reduces the constant factor by roughly one-half.
A simple improvement would be to change the for loop to break out when it finds a factor:
for (i = 2; i <= ceiling && !factorFound; i++) {
if (input % i == 0) {
factorFound = 1;
Another possibility would be to increment the counter by 2 (after checking 2 itself).
can you suggest an improvement
Here you go ... not for the algorithm, but for the program itself :)
If you aren't going to use argc and argv, get rid of them
What if I input "fortytwo"? Compare scanf() == 1, not != EOF
No need to cast the value of sqrt()
returnValue is not needed, you can return a constant: return 0;
Instead of having all of the functionality inside the main() function, separate your program in as many functions as you can think of.
You can make small cuts to your algorithm without adding too much code complexity.
For example, you can skip the even numbers on your verification, and stop the search as soon as you find a factor.
if (input < 2 || (input != 2 && input % 2 == 0))
factorFound = 1;
if (input > 3)
for (i = 3; i <= ceiling && !factorFound; i += 2)
if (input % i == 0)
factorFound = 1;
Regarding the complexity, if n is your input number, wouldn't the complexity be O(sqrt(n)), as you are doing roughly at most sqrt(n) divisions and comparisons?
Even numbers(except 2) cannot be prime numbers. So, once we know that the number is not even, we can just check if odd numbers are it's factors.
for (i = 3; i <= ceiling; i += 2) {
if (input % i == 0) {
factorFound = 1;
break;
}
}
The time complexity of your program is O(n*m^0.5). With n the number of primes in the input. And m the size of the biggest prime in the input, or MAX_INT if you prefer. So complexity could also be written as O(n) with n the number of primes to check.
With Big-O, n is (usually) the size of the input, in your case that would be the number of primes to check. If I make this list twice as big (for example duplicating it), it would take (+-) exactly twice as long, thus O(n).
Here's my algorithm, Complexity remains O(n^0.5) but i managed to remove some expensive operations in the code...
The algorithm's slowest part is the modulus operation, i've managed to eliminate sqrt or doing i * i <= n
This way i save precious cycles...its based on the fact that sum of odd numbers is always a perfect square.
Since we are iterating over odd numbers anyway, why not exploit it? :)
int isPrime(int n)
{
int squares = 1;
int odd = 3;
if( ((n & 1) == 0) || (n < 9)) return (n == 2) || ((n > 1) && (n & 1));
else
{
for( ;squares <= n; odd += 2)
{
if( n % odd == 0)
return 0;
squares+=odd;
}
return 1;
}
}
#include <stdio.h>
#include <math.h>
int IsPrime (int n) {
int i, sqrtN;
if (n < 2) { return 0; } /* 1, 0, and negatives are nonprime */
if (n == 2) { return 2; }
if ((n % 2) == 0) { return 0; } /* Check for even numbers */
sqrtN = sqrt((double)n)+1; /* We don't need to search all the way up to n */
for (i = 3; i < sqrtN; i += 2) {
if (n % i == 0) { return 0; } /* Stop, because we found a factor! */
}
return n;
}
int main()
{
int n;
printf("Enter a positive integer: ");
scanf("%d",&n);
if(IsPrime(n))
printf("%d is a prime number.",n);
else
printf("%d is not a prime number.",n);
return 0;
}
There is no way to improve the algorithm. There may be tiny ways to improve your code, but not the base speed (and complexity) of the algorithm.
EDIT: Of course, since he doesn't need to know all the factors, just whether or not it is a prime number. Great spot.