I need an optimal algorithm to find the largest divisor of a number N. Preferably in C++ or C#

前端 未结 12 1499
无人共我
无人共我 2020-12-29 11:51

I am currently using the following code but its very slow for large numbers



        static int divisor(int number)
        {
            int i;
                    


        
相关标签:
12条回答
  • 2020-12-29 11:59

    One of the industry standard methods for finding factors of large numbers is the Quadratic Sieve algorithm.

    Have a read of this:

    http://en.wikipedia.org/wiki/Quadratic_sieve

    P.S. you should also consider how big your numbers are. Different factorisation algorithms tend to perform well for a certain size, and not for others. As noted in the QS wiki article, this method is generally the fastest for numbers less than about 100 decimal digits.

    0 讨论(0)
  • 2020-12-29 11:59

    A solution if you know the smallest divisor is to apply the following formula:

    largest_d = N - N % smallest_d
    

    where N is the number whose largest divisor you're looking for.

    def largest_divisor(N, smallest_divisor):
       return N - N % smallest_divisor
    

    This code with a random big number (N = 94e15) and a random big divisor (divisor = 21e3) finished running the program in Python in 0.000740051269531 s.

    Hope this helps.

    0 讨论(0)
  • 2020-12-29 12:02

    Don't know if it's the optimal solution but you'd probably be better starting at 2 then going upwards such as:

      static int divisor(int number)
        {
            int i;
            for (i = 2; i <sqrt(number); i++)
            {
                if (number % i == 0)
                {
                    break;
                }
            }
            return number/i;
        }
    

    EDIT

    to get it to work with primes as well:

     static int divisor(int number)
        {
            int i;
            for (i = 2; i <=sqrt(number); i++)
            {
                if (number % i == 0)
                {
                    return number/i;
                }
            }
            return 1;
        }
    
    0 讨论(0)
  • 2020-12-29 12:04

    First thought you can find the smallest divisor d (not equal to 1 of course), then N/d will be the largest divisor you're looking for.

    For example if N is divisible by 3 then you'll need 2 iterations to find the answer - in your case it would be about N/6 iterations.

    Edit: To further improve your algorithm you can iterate through odd numbers only (after checking if you number is even) or, even better, if you have the list of primes pre-calculated then you can iterate through them only because smallest divisor is obviously is a prime number.

    0 讨论(0)
  • 2020-12-29 12:05

    A huge optimization (not sure if it's completely optimal - you'd have to ask a mathematician for that) is to search upwards using only prime numbers. As Vladimir and Bunnit said, it is better to search upwards, because you'll find it to be much faster. Then, return the inverse (number / i). However, if you've already tried 2 and come up dry, there is no point in trying 4 or 6. Similarly, if you've tried 3, there's no point in trying 6 or 9.

    So, if time of running is a big concern, you could have a list of the first 100 primes hard coded in your program. Test each of them. If you don't find an answer by then, then you could just increment by 2 (skipping even numbers).

    0 讨论(0)
  • 2020-12-29 12:07

    In order to limit your search space, you should start at 2 and work up to the square root of the number. There are far more numbers (in a finite search space) divisible by 2 than by 27 so you're more likely to get a low divisor than a high one, statistically speaking.

    You'll find a big difference when using the square root, rather than half the value, when you processing (for example) 1,000,000. The difference is between a search space of 500,000 for your method and 1,000 for the square root method is considerable.

    Another advantage is to halve the search space right at the front by discounting multiples of two. Then, when you have your lowest divisor, the highest one is simply the number divided by that.

    Pseudocode:

    if n % 2 == 0:              # Halve search space straight up.
        print n / 2
    else:
        i = 3                   # Start at 3.
        while i * i <= n:       # Or use i <= sqrt(n), provided sqrt is calc'ed once
            if n % i  == 0:
                print n / i     # If multiple, get opposite number, print and stop
                break
            i = i + 2           # Only need to process odd numbers
    
    0 讨论(0)
提交回复
热议问题