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;
}
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
inputis not divisible by 2, there is no need to check for 4, 6, 8, etc. If any even number divided intoinput, 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 + 1orn*6 - 1for some positive integern. To see this, just note that ifm = n*6 + 2orm = n*6 + 4, thennis divisible by 2. ifm = n*6 + 3then it is divisible by 3.In fact, we can take this further. If
p1, p2, .., pkare the firstkprimes, 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 topk. then ifgcd(k#, m) = g,gdividesn*k# + mand so this sum is trivially composite ifg != 1. so if you wanted to iterate in terms of5# = 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,gdividesn*k# + mbecause it dividesk#so it must also dividen*k#. But it dividesmas well so it must divide the sum. Above I only proved it forn = 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.