我想找到一个数字的所有精确除数。目前我有这个:

{
   int n;
   int i=2;
   scanf("%d",&n);
   while(i<=n/2)
    {
        if(n%i==0)
                  printf("%d,",i);
        i++;
     }
   getch();
}

有什么方法可以改进吗?

有帮助吗?

解决方案

首先,您的代码应该具有以下条件 i <= n/2, ,否则它可能会错过其中一个因素,例如如果n=12,则不会打印6。

运行循环到数字的平方根(即。 i <= sqrt(n))并打印两者 in/i (两者都将是n的倍数)。

{
   int n;
   int i=2;
   scanf("%d",&n);
   while(i <= sqrt(n))
    {
        if(n%i==0) {
            printf("%d,",i);
            if (i != (n / i)) {
                printf("%d,",n/i);
            }
        } 

        i++;
    }
   getch();
}

注 :

  • 对于一个完美的正方形,这样平方根就不会打印两次,额外的检查是在循环结束时完成的。 i*i == n 正如@chepner所建议的那样。
  • 如果您希望所有因子按升序将值存储在数组中,那么在循环结束时对所有数字进行排序并显示。

其他提示

通过使用c(更快)“查找所有主要因素”来查找所有除数 最多18位。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

unsigned int FindDivisors(unsigned long long divisors[], unsigned long long N) {
    unsigned int lastdiv = 0;
    divisors[lastdiv++] = 1;
    unsigned long long powerfactor = 1;
    unsigned long long number = N;
    while ((number & 1) == 0) {
        powerfactor <<= 1;
        divisors[lastdiv++] = powerfactor;
        number >>= 1;
    }

    unsigned long long factor = 3; unsigned long long upto = lastdiv;
    powerfactor = 1;
    while (factor * factor <= number) {
        if (number % factor == 0) {
            powerfactor *= factor;
            for (unsigned int i = 0; i < upto; i++)
                divisors[lastdiv++] = divisors[i] * powerfactor;
            number /= factor;
        }
        else {
            factor += 2; upto = lastdiv;
            powerfactor = 1;
        }
    }

    if (number > 1) {
        if (number != factor) {
            upto = lastdiv;
            powerfactor = 1;
        }
        powerfactor *= number;
        for (unsigned int i = 0; i < upto; i++)
            divisors[lastdiv++] = divisors[i] * powerfactor;
    }
    return lastdiv;
}

int cmp(const void *a, const void *b) {
    if( *(long long*)a-*(long long*)b < 0 ) return -1;
    if( *(long long*)a-*(long long*)b > 0 ) return 1;
    return 0;
}

int main(int argc, char *argv[]) {
    unsigned long long N = 2;
    unsigned int Ndigit = 1;
    if (argc > 1) {
        N = strtoull(argv[1], NULL, 10);
        Ndigit = strlen(argv[1]);
    }
    unsigned int maxdiv[] = {1, 4, 12, 32, 64, 128, 240, 448, 768, 1344,
                             2304, 4032, 6720, 10752, 17280, 26880, 41472, 64512, 103680};

    unsigned long long divisors[maxdiv[Ndigit]];
    unsigned int size = FindDivisors(divisors, N);
    printf("Number of divisors = %u\n", size);

    qsort(divisors, size, sizeof(unsigned long long), cmp);
    for (unsigned int i = 0; i < size; i++)
        printf("%llu ", divisors[i]);
    printf("\n");

    return 0;
}
.

简单的线性搜索可以通过首先扔掉所有 2 的因子来改进。这可以通过简单的位移位或使用良好的内在函数来计算训练零来完成。无论哪种情况都非常快。然后运行 ​​shg 建议的算法(由于不存在 2 的幂,运行速度会快得多),并将结果与​​所有可能的 2 的幂结合起来(不要忘记这一步)。它对于具有大量训练零的输入有很大帮助,但如果它们没有,它甚至会有所帮助 - 您不必再测试任何偶数除数,因此循环的长度减半。

扔掉一些恒定的低因子(但大于 2)也有帮助。使用常量取模几乎肯定是由编译器优化的(或者如果没有,您可以自己优化),但更重要的是,这意味着需要测试的除数更少。不要忘记将该因子与您找到的除数结合起来。

您还可以完全分解数字(使用您最喜欢的算法 - 可能 Pollard 的 Rho 是最好的),然后打印因子的所有乘积(空乘积和满乘积除外)。对于更大的输入,这很有可能会更快 - 与简单的线性搜索相比,Pollard 的 Rho 算法可以非常快地找到因子,因子通常少于真除数,最后一步(枚举乘积)仅涉及快速数学(没有部门)。这对于因数非常小的数字很有帮助,Rho 发现这种数字最快。

其中一个答案中显示的代码有一个很难看到的错误。如果 sqrt(n) 是有效的除数;但是 n 不是一个完美的平方数,则省略两个结果。

例如。试试 n = 15, ,看看会发生什么; sqrt(15) = 3, ,所以while循环的最后一个值是2。执行的下一个语句 if (i * i == n) 将被执行为 if(3 * 3 == 15).所以3没有被列为除数,也错过了5。

下面将正确处理正整数的一般情况。

 {
   int n;
   int i=2;
   scanf("%d",&n);
   while(i <= sqrt(n))
    {
        if(n%i==0) {
            printf("%d,",i);
            if (i != (n / i)) {
                printf("%d,",n/i);
            }
        } 

        i++;
    }
   getch();
}
  int count = 2;
     //long childsum = 0;
           long _originalvalue = sum;
     dividend = "1";
     for (int i = 2; i < sum; i++)
     {
         if (_originalvalue % i == 0)
         {
             sum = _originalvalue / i;
             //sum = childsum;
             dividend = dividend + "," + i+","+sum;
             if (sum == i)
             {
                 count++;
             }
             else
             {
                 count = count + 2;
             }
         }
     }
     return count;
.

当给定的数字是奇数时,我们甚至可以跳过数字。 接受代码中的轻微即兴创作:)

它是查找给定数量因子的Java代码。

import java.util.Scanner;
public class Factors {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t=scanner.nextInt();
        while(t-- > 0) {
            int n = scanner.nextInt();
            if(n % 2 == 0) {
                for(int i = 1; i <= Math.sqrt(n); i++) {
                    if(n % i == 0) {
                        System.out.println(i + ", ");
                        if(i != n/i) {
                            System.out.println(n/i + ", ");
                        }
                    }
                }
            }
            else {
                for(int i = 1; i <= Math.sqrt(n); i=i+2) {
                    if(n % i == 0) {
                        System.out.println(i + ", ");
                        if(i != n/i) {
                            System.out.println(n/i + ", ");
                        }
                    }
                }
            }
        }
    }
}
.

这是我的新C#版本。由于RNDM,它比第一次尝试快50倍。

public static long GetDivisors(long number)
    {
        long divisors = 0;

        long boundary = (long)Math.Sqrt(number);

        for (int i = 1; i <= boundary; i++)
        {
            if (number % i == 0)
            {
                divisors++;
                if(i != (number / i))
                {
                    if (i * i != number)
                    {
                        divisors++;
                    }
                }
            }
        }

        return divisors;
    }
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top