I have written this PrimeFactorize
utility method in C# (using LINQPad) which works fine, but feels like it is a bit slow, I was wondering what might be improved. Also looking for any criticism not related to efficiency to make the code better.
// Generate prime factors for a number, e.g., input 12 returns 2 2 3
public static IEnumerable<int> PrimeFactorize(int number)
{
if(IntUtils.IsPrime(number))
{
yield return number;
}
else
{
List<int> primes = IntUtils.GetPrimesBetween(2, number);
while(!IntUtils.IsPrime(number))
{
foreach(var p in primes)
{
if(number % p == 0)
{
yield return p;
number /= p;
break;
}
}
}
yield return number;
}
}
As a note, the IntUtils.IsPrime
and IntUtils.GetPrimesBetween
are two other utility methods I wrote. I am including GetPrimesBetween
below. IsPrime
has already been reviewed and it is quite fast by itself and can be found on GitHub.
public static List<int> GetPrimesBetween(int min, int max)
{
var primes = new List<int>();
for(var i = min; i <= max; i++)
{
if(IntUtils.IsPrime(i) && i != 1)
{
primes.Add(i);
}
}
return primes;
}
Here is a test run, along with the execution times:
void Main()
{
var N = 12;
for(var i = 1; i <= 10; i++)
{
Console.Write("Run # {0} | Number to factorize: {1}\nResult: ", i, N);
foreach(var P in IntUtils.PrimeFactorize(N))
{
Console.Write(P + " ");
}
// mix up results a bit
N += N*3 + i;
Console.WriteLine("\nTime elapsed since start: {0}", Util.ElapsedTime);
}
}
Results:
Run # 1 | Number to factorize: 12
Result: 2 2 3
Time elapsed since start: 00:00:00.0130129
Run # 2 | Number to factorize: 49
Result: 7 7
Time elapsed since start: 00:00:00.0132697
Run # 3 | Number to factorize: 198
Result: 2 3 3 11
Time elapsed since start: 00:00:00.0133637
Run # 4 | Number to factorize: 795
Result: 3 5 53
Time elapsed since start: 00:00:00.0139543
Run # 5 | Number to factorize: 3184
Result: 2 2 2 2 199
Time elapsed since start: 00:00:00.0183778
Run # 6 | Number to factorize: 12741
Result: 3 31 137
Time elapsed since start: 00:00:00.0528457
Run # 7 | Number to factorize: 50970
Result: 2 3 5 1699
Time elapsed since start: 00:00:00.2867861
Run # 8 | Number to factorize: 203887
Result: 31 6577
Time elapsed since start: 00:00:01.9602979
Run # 9 | Number to factorize: 815556
Result: 2 2 3 7 7 19 73
Time elapsed since start: 00:00:13.5247897
Run # 10 | Number to factorize: 3262233
Result: 3 13 233 359
Time elapsed since start: 00:01:35.3379070
As you can see, starting at Run #6 the times start getting a lot longer very quickly, and by Run # 10 it takes over a minute to get the results.
GetPrimesBetween
would be to pre-allocate theList<int>
with an approximate number of primes:var primes = new List<int>((int)Math.Round(max / Math.Log(max) - min / Math.Log(min)));
\$\endgroup\$