I've written a small C program to calculate primes and now try to optimize the code as far as I can.
In the first revision of the program I was checking if a number was even (modulo 2) and if it was I would continue to the next number.
In my second revision I tried only checking odd numbers to be possible primes by incrementing the number I would be checking by 2 (so I would start from 3, then check 5, then 7, then 9, then 11 etc etc).
I thought this would be way faster as I had cut an extra check for modulo 2 with my code and simply replaced it with an addition. However, to my surprise the code checking only odd numbers, runs a tad bit slower most of the times then the implementation checking all numbers.
Here is the code(it contains the changes I made between revisions in comments wherever it says //CHANGE)
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
unsigned long i = 3; //CHANGE No 1 - it was i = 2;
bool hasDivisor(unsigned long number)
{
//https://stackoverflow.com/questions/5811151/why-do-we-check-up-to-the-square-root-of-a-prime-number-to-determine-if-it-is-pr
unsigned long squareRoot = floor(sqrt(number));
//we don't check for even divisors - we want to check only odd divisors
//CHANGE No 2 - it was (number%2 ==0)
if(!((squareRoot&1)==0)) //thought this would boost the speed
{
squareRoot += 1;
}
for(unsigned long j=3; j <= squareRoot; j+=2)
{
//printf("checking number %ld with %ld \n", number, j);
if(number%j==0)
{
return true;
}
}
return false;
}
int main(int argc, char** argv)
{
printf("Number 2 is a prime!\n");
printf("Number 3 is a prime!\n");
while(true)
{
//even numbers can't be primes as they are a multiple of 2
//so we start with 3 which is odd and contiously add 2
//that we always check an odd number for primality
i++; //thought this would boost the speed instead of i +=2;
i++; //CHANGE No 3 - it was a simple i++ so eg 3 would become 4 and we needed an extra if(i%2==0) here
//search all odd numbers between 3 and the (odd ceiling) sqrt of our number
//if there is perfect division somewhere it's not a prime
if(hasDivisor(i))
{
continue;
}
printf("Number %ld is a prime!\n", i);
}
return 0;
}
I'm using Arch Linux x64 with GCC version 8.2.1 and compiling with:
gcc main.c -lm -O3 -o primesearcher
Although I tested with O1 and O2, as well.
I'm "benchmarking" with the command below:
./primesearcher & sleep 10; kill $!
which runs the program for 10seconds and outputs primes to the terminal for that time and then kills it. I obviously tried allowing the program to run more (30, 60 and 180 seconds) but the results are about 9/10 of the time in favor of the version checking even numbers (modulo 2 version has found a bigger prime before it got killed).
Any idea why would this be happening? Maybe something wrong in terms of code in the end?