It is possible to optimize the looping to perform the calculation of dividers more efficiently:
- defining the counter
c
like 2,
- the beginning of the cycle as 2,
- the end for the square root of
num
plus 1 (sqrt(num)+1
),
- and adding 1 to the counter
c
each iteration if the divisor is the root itself, or 2 if it is not.
The looping gets that way:
c = 2;
for(i=2; i<((int)floor(sqrt(num)))+1; i++)
{
if(num % i == 0)
{
c += (num/i == i) ? 1 : 2;
}
}
Explaining: For each divider i
less than the square root, there is a reciprocal num/i
larger than the square root.
Example: dividers of 64:
1
2
4
8 <== raiz quadrada
16 <== recíproco 64/4
32 <== recíproco 64/2
64 <== recíproco 64/1
Running the program without optimization for num=10^10
:
Tempo total = 132.3230133580 segundos
número de divisores e 121
With optimization, time reduces significantly (also for num=10^10
):
Tempo total = 0.0014944220 segundos
número de divisores e 121
The explanation for the increase in performance is the change in the complexity of O(n) for O(sqrt(n)), i.e., the looping will count up to 100,000 instead of 10,000,000.
Times were measured with the function clock_gettime().
Below is the full program used for the test:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int main()
{
struct timespec inicio, fim;
double demora;
long long int num=10000000000, i;
int c;
clock_gettime(CLOCK_MONOTONIC, &inicio); // início do cronômetro
#if 0
// Algoritmo original
c = 0;
for(i=1; i<=num; i++)
{
if(num%i==0)
{
c+=1;
}
}
#else
// Algoritmo otimizado
c = 2;
for(i=2; i<((int)floor(sqrt(num)))+1; i++)
{
if(num%i==0)
{
c += (num/i == i) ? 1 : 2;
}
}
#endif
clock_gettime(CLOCK_MONOTONIC, &fim); // fim do cronômetro
demora = (fim.tv_sec - inicio.tv_sec) + (fim.tv_nsec - inicio.tv_nsec)/1E9;
printf("Tempo total = %.10lf segundos\n", demora);
printf ("número de divisores e %d",c);
}
tested with gcc version 8.1.0 - Mingw-W64
What is a "very large" number? Or: what would be the largest possible number for the program to process?
– Gomiero
The number can reach up to 10 9
– rafael marques