简体   繁体   English

找出数字的最大因数(自身除外)

[英]Find the greatest factor of a number (other than itself)

What is an optimal way to find the greatest factor of a number (other than itself)? 找到一个数的最大因数(本身除外)的最佳方法是什么? So far, I've got this: 到目前为止,我已经知道了:

function biggestFactor(num) {
  if (num % 2 == 0) return num / 2;
  var result;
  for (var i = 1, m = Math.floor(num / 2); i < m; i++) {
    if (num % i == 0) result = i;
  }
  return result;
}

greatestFactor(1024); // 512
greatestFactor(1025); // 205
greatestFactor(1026); // 513
greatestFactor(1027); // 79

This is obviously not so efficient. 这显然不是那么有效。 What are other ways to solve this? 还有什么其他方法可以解决这个问题?

Your requirement is to remove the smallest prime from "num" 您的要求是从“ num”中删除最小的素数

  • Testing 2 is ok, than start at 3 till to squareroot(num) 测试2可以,然后从3开始直到平方根(num)
  • You should increment by 2 您应该增加2
  • The result is num / i , not just i ( i is the smallest prime of num ) 结果是num / i ,而不仅仅是iinum的最小素数)

(First I was wrong because I thought you are looking for the greatest prime) (首先我错了,因为我以为你正在寻找最好的素数)

Now a tested version 现在是经过测试的版本

 function biggestFactor(num) { if (num % 2 == 0) return num / 2; var stop = Math.sqrt(num); for (var i = 3; i <= stop; i += 2) { // = because of prime squares if ((num % i) == 0) { // test if integer return num / i; // return of smallest prime } } return num; // no int or < 2 } for (var num = 10; num < 40; num ++) { console.log(num + ' => ' + biggestFactor(num)); } 

First, as indicated by a lot of comments/posts here, you need a fast way of identifying prime numbers. 首先,正如此处的许多评论/帖子所表明的那样,您需要一种识别素数的快速方法。 I'll give you the code in C++, but it should be relatively easy to convert to JavaScript. 我将为您提供C ++中的代码,但转换为JavaScript应该相对容易。

/**
 * Miller Rabin primality test
 * Returns true if n is probably prime
 * optionally, you can specify a vector of witnesses to test against
 * leave empty if you want the algorithm to randomly generate witnesses
 */
static bool isProbablePrime(ulong n, std::vector<ulong> w)
        {
            // easy
            if(n==2 || n==3 || n==5 || n==7)
            {
                return true;
            }
            if(n<10)
            {
                return false;
            }

            // write (n-1) as 2 ^ s * d
            auto d = n - 1L;
            auto s = 0L;
            while(d%2==0)
            {
                d/=2;
                s++;
            }

            // witness loop
            std::random_device rd;
            std::mt19937 gen(rd());
            std::uniform_int_distribution<ulong> dis(1, n - 1);
            bool nextWitness = false;
            for(int k=0; k<(w.empty() ? 10 : w.size()); k++)
            {
                // random base between 1 and n - 1
                auto a = w.empty() ? dis(gen) : w[k];

                // mod pow
                auto x = modpow(a, d, n);

                if(x == 1 || x == n - 1)
                {
                    continue;
                }

                // modular exponentiation with repeated squaring
                for(auto i=s-1; i>=0; i--)
                {
                    x = (x * x) % n;

                    // composite
                    if(x == 1)
                    {
                        return false;
                    }

                    if(x==n-1)
                    {
                        // the behaviour of this flag, and the break are meant to emulate a 'continue <loopname>' statement
                        nextWitness = true;
                        break;
                    }
                }
                if(!nextWitness)
                {
                    return false;
                }
                nextWitness = false;
            }

            // probably prime
            return true;
        }

Now you can easily write a piece of code that generates the next prime number: 现在,您可以轻松编写一段代码来生成下一个质数:

static ulong nextPrime(ulong p)
        {
            p++;
            while(!isProbablePrime(p))
            {
                p++;
            }
            return p;
        }

Next (final) step is to iterate over numbers starting at 2, and when a number is found that divides the input, return the corresponding largest divisor. 下一步(最后一个步骤)是迭代从2开始的数字,当找到一个将输入除以数字时,返回相应的最大除数。

long largestDivisor(long n)
{
    long f = 2;
    while(f < sqrt(n))
    {
        if(n % f == 0)
            return n/f;
        f = nextPrime(f);
    }
    return n;
}

I can propose a O(sqrt(N)) approach where N is the number 我可以提出O(sqrt(N))方法,其中N是数字

 function biggestFactor(num) { let result = 1; for(let i=2; i*i <=num; i++){ if(num%i==0){ result = num/i; break; } } console.log(result); return result; } biggestFactor(1024); // 512 biggestFactor(1025); // 205 biggestFactor(1026); // 513 biggestFactor(1027); // 79 

Just traverse through 2 to sqrt(N), 只需遍历2到sqrt(N),

if N = i*(N/i) 如果N = i *(N / i)
then N/i is the biggest number possible, so break at this point 那么N / i是最大的数字,所以在这一点上休息

If you know the number is not a prime or even then this should work. 如果您知道该数字不是素数,那么应该可以。

function greatestFactor(num) {
  for (var i = 3; num%i>0; ) i+=2;
  return num/i;
}

It will be slow if the smallest factor is large though 如果最小的因素很大,那将会很慢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM