The most efficient way to get all number divisors

Possible duplicate:
Effectively find all the divisors of the number

This is a much more efficient question than the general β€œfind a way to do this,” but after getting some odd results, I want to see if anyone can tell me why the latter method is so inefficient:

method 1: brute force, without optimization

public static List<int> proper_divisors(int x) { List<int> toreturn = new List<int>(); for (int i = 1; i <= Math.Floor(Math.Sqrt(x)); i++) { if (x % i == 0) { toreturn.Add(i); toreturn.Add(x / i); } } if (toreturn.ElementAt(toreturn.Count() / 2) == toreturn.ElementAt(toreturn.Count() / 2 - 1)) { toreturn.Remove(toreturn.ElementAt(toreturn.Count() / 2)); } return toreturn; } 

path 2: the same as before, but this time check if it is primary first (since these cases take the most time, using the miller-rabin for a simple check)

  public static List<int> proper_divisors(int x) { List<int> toreturn = new List<int>(); if (!isprime(x)) { for (int i = 1; i <= Math.Floor(Math.Sqrt(x)); i++) { if (x % i == 0) { toreturn.Add(i); toreturn.Add(x / i); } } if (toreturn.ElementAt(toreturn.Count() / 2) == toreturn.ElementAt(toreturn.Count() / 2 - 1)) { toreturn.Remove(toreturn.ElementAt(toreturn.Count() / 2)); } } else { toreturn.Add(1); toreturn.Add(x); } return toreturn; } 

what, in his opinion, would be the fastest way, was method 3, as he reduced the number with which he worked every time he found the main factor, and he only tried prime numbers (they were created by a sieve at runtime takes about 34 ms to get all primes less than a million). The last thing to do was to take the main factors and their authority and make a list of all the factors.

method 3:

  public static HashSet<int> prime_factors(int x) { if (!isprime(x)) { List<int> toreturn = new List<int>(); int i = 0; while (primes[i] <= x) { if (x % primes[i] == 0) { toreturn.Add(primes[i]); x = x / primes[i]; } else { i++; } } var power_set_primes = GetPowerSet(toreturn); var factors = new HashSet<int>(); foreach (var p in power_set_primes) { var factor = p.Select(z => z).Aggregate(1, (z, y) => z * y); factors.Add(factor); } return factors; } else { HashSet<int> toreturn = new HashSet<int>(); toreturn.Add(1); toreturn.Add(x); return toreturn; } public static IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list) { return from m in Enumerable.Range(0, 1 << list.Count) select from i in Enumerable.Range(0, list.Count) where (m & (1 << i)) != 0 select list[i]; } 

Time spent on the factor of the first million numbers: path 1: 7223 ms path 2: 8985 ms (the usual check is not worth it for small numbers, I think) path 3: 49423 ms

so my question is twofold: 1) why is path 3 so slow ??? 2) is there something that can make it faster? as an exception, primes were calculated as a list and then converted to an array, as I thought it would be faster. bad move?

+6
source share
1 answer

This is the subject area of ​​integer factorization. There are a number of well-known algorithms:

http://en.wikipedia.org/wiki/Integer_factorization#Factoring_algorithms

I suggest you choose the best match + profile.


my original comment:

Profile Profile Profile. Also, do not use encoders or LINQ if you need efficiency. Write it in C and use P / Invoke. In general, do not ask if you can measure it.

0
source

Source: https://habr.com/ru/post/886876/


All Articles