C-给定数的最大素因子

C-给定数的最大素因子,c,execution-time,C,Execution Time,我已经编写了以下代码来计算所提供数字的最大素数因子 通过标准输入,但执行起来需要很长时间。如何减少程序的执行时间 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> bool is_prime(unsigned long long num) { if (num == 0 || num == 1) return false; if (num == 2)

我已经编写了以下代码来计算所提供数字的最大素数因子 通过标准输入,但执行起来需要很长时间。如何减少程序的执行时间

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

bool is_prime(unsigned long long num)
{
    if (num == 0 || num == 1)
        return false;
    if (num == 2)
        return true;
    for (unsigned long long j = 2; j < num; j++)
        if(num%j==0)
            return false;

    return true;
}

int main(void)
{
    unsigned long long n,i;
    printf("enter the number: ");
    scanf("%llu",&n);
    for(i=n-1;i>1;i--)
        if((is_prime(i)) && n%i==0)
            break;
    printf("%llu\n",i);

    return 0;
}
#包括
#包括
#包括
布尔是素数(无符号长数值)
{
如果(num==0 | | num==1)
返回false;
如果(num==2)
返回true;
for(无符号长j=2;j1;i--)
如果((is_prime(i))&&n%i==0)
打破
printf(“%llu\n”,i);
返回0;
}

输入中的数字是600851475143。

保持相同的逻辑,您可以通过仅执行循环直到sqrt(num)来减少时间。 因为如果它不是素数,至少会有一个小于sqrt(num)的除数

让我们假设num不是素数。所以对于一些1 所以a或b都应该小于sqrt(num)

因此,应该将is_prime的代码更改为如下代码

bool is_prime(unsigned long long num)
{
    if (num == 0 || num == 1)
        return false;
    if (num == 2)
        return true;
    long long root_num = sqrt(num);
    for (unsigned long long j = 2; j < root_num; j++)
        if(num%j==0)
            return false;

    return true;
}
bool是素数(无符号长数值)
{
如果(num==0 | | num==1)
返回false;
如果(num==2)
返回true;
长根_num=sqrt(num);
for(无符号长j=2;j

现在,若你们想改变你们的逻辑,那个么有一种叫做筛法的算法,它可以找到所有小于给定数的素数。检查这个

main()中循环中的if语句应该首先检查n%i==0,这样就不会检查非因子的素数。在我在现代英特尔CPU上运行的一个简单测试用例中,仅此一项就可以使程序在从1到2000的所有数字上的速度提高200倍以上。下面的mod just to main()(我将其分解为一个返回最大素数因子的函数)大大提高了速度。我也认为数字本身是一个可能的因素(不是原始的)。
unsigned long long最大素数因子(unsigned long long n)
{
无符号长i,sqrtn,maxprime;
if(is_素数(n))
返回(n);
sqrtn=(无符号长)sqrt((双)n);
maxprime=1;
对于(i=2;i
bool是素数(无符号长数值)
{
if(num<2)返回false;/*拒绝边界案例*/
如果(num==2)返回true;/*接受最大的偶数素数*/
如果((num&(~1))==num)返回false;/*拒绝所有其他even*/
unsigned long long limit=sqrt(num)+1;/*限制搜索范围*/
对于(无符号长j=3;j
玩得开心…一个函数用于所有基本因子,一个函数用于最大基本因子:

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

typedef unsigned long long u64_t;

static size_t prime_factors(u64_t value, u64_t *array)
{
    size_t n_factors = 0;
    u64_t n = value;
    u64_t i;

    while (n % 2 == 0)
    {
        n /= 2;
        //printf("Factor: %llu (n = %llu)\n", 2ULL, n);
        array[n_factors++] = 2;
    }

    while (n % 3 == 0)
    {
        n /= 3;
        //printf("Factor: %llu (n = %llu)\n", 3ULL, n);
        array[n_factors++] = 3;
    }

    for (i = 6; (i - 1) * (i - 1) <= n; i += 6)
    {   
        while (n % (i-1) == 0)
        {
            n /= (i-1);
            //printf("Factor: %llu (n = %llu)\n", (i-1), n);
            array[n_factors++] = (i-1);
        }
        while (n % (i+1) == 0)
        {
            n /= (i+1);
            //printf("Factor: %llu (n = %llu)\n", (i+1), n);
            array[n_factors++] = (i+1);
        }
    }
    if (n != 1)
        array[n_factors++] = n;

    return n_factors;
}

static u64_t max_prime_factor(u64_t value)
{
    u64_t n = value;
    u64_t i;
    u64_t max = n;

    while (n % 2 == 0)
    {
        n /= 2;
        //printf("Factor: %llu (n = %llu)\n", 2ULL, n);
        max = 2;
    }

    while (n % 3 == 0)
    {
        n /= 3;
        //printf("Factor: %llu (n = %llu)\n", 3ULL, n);
        max = 3;
    }

    for (i = 6; (i - 1) * (i - 1) <= n; i += 6)
    {   
        while (n % (i-1) == 0)
        {
            n /= (i-1);
            //printf("Factor: %llu (n = %llu)\n", (i-1), n);
            max = (i-1);
        }
        while (n % (i+1) == 0)
        {
            n /= (i+1);
            //printf("Factor: %llu (n = %llu)\n", (i+1), n);
            max = (i+1);
        }
    }
    //printf("Max Factor = %llu\n", (n == 1) ? max : n);

    return (n == 1) ? max : n;
}

static void print_factors(u64_t value, size_t n_factors, u64_t *factors)
{
    printf("%20llu:", value);
    int len = 21;
    for (size_t i = 0; i < n_factors; i++)
    {
        if (len == 0)
            len = printf("%.21s", "");
        len += printf(" %llu", factors[i]);
        if (len >= 60)
        {
            putchar('\n');
            len = 0;
        }
    }
    if (len > 0)
        putchar('\n');
}

void builtin_tests(void)
{
    u64_t tests[] =
    {
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
        19, 20, 25, 49, 63, 69, 71, 73, 825, 829, 1000, 6857, 73112,
        731122, 7311229, 73112293, 731122935, 7311229357, 73112293571,
        600851475143, 731122935711, 7311229357111,
        18446744073709551610ULL, 18446744073709551611ULL,
        18446744073709551612ULL, 18446744073709551613ULL,
        18446744073709551614ULL, 18446744073709551615ULL,
    };
    u64_t factors[64];

    for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
    {
        u64_t max = max_prime_factor(tests[i]);
        printf("%20llu -> Max Prime Factor = %llu\n", tests[i], max);
        size_t n_factors = prime_factors(tests[i], factors);
        print_factors(tests[i], n_factors, factors);
    }
}

int main(int argc, char **argv)
{
    if (argc == 1)
        builtin_tests();
    else
    {
        for (int i = 1; i < argc; i++)
        {
            u64_t factors[64];
            u64_t value = strtoull(argv[i], 0, 0);
            u64_t max = max_prime_factor(value);
            printf("%20llu -> Max Prime Factor = %llu\n", value, max);
            size_t n_factors = prime_factors(value, factors);
            print_factors(value, n_factors, factors);
        }
    }
    return 0;
}

最好从数字的平方根开始循环到3, 同样,您可以跳过偶数


因此,您可以在短时间内得到答案。

is prime
中,除了检查2之外,您只需要检查奇数直到
num
的平方根。有关一些有用的信息,请参阅。如果一个数的一个因子大于其平方根,则它的相应因子也必须小于平方根。因此,您可以只需检查平方根即可找到这些因子中的较低者。
for(unsigned long j=2;
效率低下,因为您之前已经检查了2。请改用
for(unsigned long j=3;
。哦,不,O(1)额外的工作。在找到数字时将它们分开。这会使搜索保持较小的范围。而且,直到最后,你才真正关心因子是否为素数,所以不要测试素数。这比除法更昂贵。如果你先测试较小的数,那么你已经知道找到的第一个因子是素数。(如果不是,你会首先找到其中一个因素。)一个包含前百万个素数的硬编码表也会有所帮助。当然
for(unsigned long j=3;j
会更好?(2已经过测试,剩余的素数必须是奇数)嘿,罗杰,我说过最好在is_素数函数中保持相同的逻辑我们不是在寻找素数因子。我们是在寻找一个数的除数,对吗?跳过偶数来测试is_素数是另一回事。如果你在寻找一个数的除数,而你已经发现2不是其中之一,那么检查任何其他偶数都没有意义,因为如果偶数是一个除数,那么2也将是一个除数所以你只需要检查奇数除数就可以把循环的大小减半。先生,你是对的。但我要说的是,即使你做了j+=2,在复杂度上也没有任何区别。它将是O(num/2)。也就是说,仍然是O(num),这与原始代码相同。当然,这会有点效率,但不是因为复杂度。这就是为什么我没有要求他做j+=2;谢谢。好的,但他问的是如何减少执行时间,这就是为什么我的评论是相关的。这是一个小问题,其他人在回答中已经考虑到了这一点,所以我只是认为您希望你的也可以,这没什么大不了的。我不需要测试编译器。sqrt(num)长-长是一种值得怀疑的方法。
j
应该是
j@chrono我在限制上加了一个。我的OCD不像64位整数那么重要,确实应该有一个函数来完成这项工作,而不需要从double到double的转换。确实应该有,但这并不困难是的。代码也在那里。例如。
bool is_prime(unsigned long long num)
{
    if (num <  2) return false;      /* Reject border cases */

    if (num == 2) return true;       /* Accept the largest even prime */

    if ((num & (~1)) == num) return false;  /* Reject all other evens */

    unsigned long long limit = sqrt(num) + 1;  /* Limit the range of the search */

    for (unsigned long long j = 3; j < limit; j += 2)  /* Loop through odds only */
        if(num % j==0)
            return false;           /* Reject factors */

    return true;                    /* No factors, hence it is prime */

}
#include <stdio.h>
#include <stdlib.h>

typedef unsigned long long u64_t;

static size_t prime_factors(u64_t value, u64_t *array)
{
    size_t n_factors = 0;
    u64_t n = value;
    u64_t i;

    while (n % 2 == 0)
    {
        n /= 2;
        //printf("Factor: %llu (n = %llu)\n", 2ULL, n);
        array[n_factors++] = 2;
    }

    while (n % 3 == 0)
    {
        n /= 3;
        //printf("Factor: %llu (n = %llu)\n", 3ULL, n);
        array[n_factors++] = 3;
    }

    for (i = 6; (i - 1) * (i - 1) <= n; i += 6)
    {   
        while (n % (i-1) == 0)
        {
            n /= (i-1);
            //printf("Factor: %llu (n = %llu)\n", (i-1), n);
            array[n_factors++] = (i-1);
        }
        while (n % (i+1) == 0)
        {
            n /= (i+1);
            //printf("Factor: %llu (n = %llu)\n", (i+1), n);
            array[n_factors++] = (i+1);
        }
    }
    if (n != 1)
        array[n_factors++] = n;

    return n_factors;
}

static u64_t max_prime_factor(u64_t value)
{
    u64_t n = value;
    u64_t i;
    u64_t max = n;

    while (n % 2 == 0)
    {
        n /= 2;
        //printf("Factor: %llu (n = %llu)\n", 2ULL, n);
        max = 2;
    }

    while (n % 3 == 0)
    {
        n /= 3;
        //printf("Factor: %llu (n = %llu)\n", 3ULL, n);
        max = 3;
    }

    for (i = 6; (i - 1) * (i - 1) <= n; i += 6)
    {   
        while (n % (i-1) == 0)
        {
            n /= (i-1);
            //printf("Factor: %llu (n = %llu)\n", (i-1), n);
            max = (i-1);
        }
        while (n % (i+1) == 0)
        {
            n /= (i+1);
            //printf("Factor: %llu (n = %llu)\n", (i+1), n);
            max = (i+1);
        }
    }
    //printf("Max Factor = %llu\n", (n == 1) ? max : n);

    return (n == 1) ? max : n;
}

static void print_factors(u64_t value, size_t n_factors, u64_t *factors)
{
    printf("%20llu:", value);
    int len = 21;
    for (size_t i = 0; i < n_factors; i++)
    {
        if (len == 0)
            len = printf("%.21s", "");
        len += printf(" %llu", factors[i]);
        if (len >= 60)
        {
            putchar('\n');
            len = 0;
        }
    }
    if (len > 0)
        putchar('\n');
}

void builtin_tests(void)
{
    u64_t tests[] =
    {
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
        19, 20, 25, 49, 63, 69, 71, 73, 825, 829, 1000, 6857, 73112,
        731122, 7311229, 73112293, 731122935, 7311229357, 73112293571,
        600851475143, 731122935711, 7311229357111,
        18446744073709551610ULL, 18446744073709551611ULL,
        18446744073709551612ULL, 18446744073709551613ULL,
        18446744073709551614ULL, 18446744073709551615ULL,
    };
    u64_t factors[64];

    for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
    {
        u64_t max = max_prime_factor(tests[i]);
        printf("%20llu -> Max Prime Factor = %llu\n", tests[i], max);
        size_t n_factors = prime_factors(tests[i], factors);
        print_factors(tests[i], n_factors, factors);
    }
}

int main(int argc, char **argv)
{
    if (argc == 1)
        builtin_tests();
    else
    {
        for (int i = 1; i < argc; i++)
        {
            u64_t factors[64];
            u64_t value = strtoull(argv[i], 0, 0);
            u64_t max = max_prime_factor(value);
            printf("%20llu -> Max Prime Factor = %llu\n", value, max);
            size_t n_factors = prime_factors(value, factors);
            print_factors(value, n_factors, factors);
        }
    }
    return 0;
}
                   1 -> Max Prime Factor = 1
                   1:
                   2 -> Max Prime Factor = 2
                   2: 2
                   3 -> Max Prime Factor = 3
                   3: 3
                   4 -> Max Prime Factor = 2
                   4: 2 2
                   5 -> Max Prime Factor = 5
                   5: 5
                   6 -> Max Prime Factor = 3
                   6: 2 3
                   7 -> Max Prime Factor = 7
                   7: 7
                   8 -> Max Prime Factor = 2
                   8: 2 2 2
                   9 -> Max Prime Factor = 3
                   9: 3 3
                  10 -> Max Prime Factor = 5
                  10: 2 5
                  11 -> Max Prime Factor = 11
                  11: 11
                  12 -> Max Prime Factor = 3
                  12: 2 2 3
                  13 -> Max Prime Factor = 13
                  13: 13
                  14 -> Max Prime Factor = 7
                  14: 2 7
                  15 -> Max Prime Factor = 5
                  15: 3 5
                  16 -> Max Prime Factor = 2
                  16: 2 2 2 2
                  17 -> Max Prime Factor = 17
                  17: 17
                  18 -> Max Prime Factor = 3
                  18: 2 3 3
                  19 -> Max Prime Factor = 19
                  19: 19
                  20 -> Max Prime Factor = 5
                  20: 2 2 5
                  25 -> Max Prime Factor = 5
                  25: 5 5
                  49 -> Max Prime Factor = 7
                  49: 7 7
                  63 -> Max Prime Factor = 7
                  63: 3 3 7
                  69 -> Max Prime Factor = 23
                  69: 3 23
                  71 -> Max Prime Factor = 71
                  71: 71
                  73 -> Max Prime Factor = 73
                  73: 73
                 825 -> Max Prime Factor = 11
                 825: 3 5 5 11
                 829 -> Max Prime Factor = 829
                 829: 829
                1000 -> Max Prime Factor = 5
                1000: 2 2 2 5 5 5
                6857 -> Max Prime Factor = 6857
                6857: 6857
               73112 -> Max Prime Factor = 37
               73112: 2 2 2 13 19 37
              731122 -> Max Prime Factor = 52223
              731122: 2 7 52223
             7311229 -> Max Prime Factor = 24953
             7311229: 293 24953
            73112293 -> Max Prime Factor = 880871
            73112293: 83 880871
           731122935 -> Max Prime Factor = 89107
           731122935: 3 5 547 89107
          7311229357 -> Max Prime Factor = 7311229357
          7311229357: 7311229357
         73112293571 -> Max Prime Factor = 8058227
         73112293571: 43 211 8058227
        600851475143 -> Max Prime Factor = 6857
        600851475143: 71 839 1471 6857
        731122935711 -> Max Prime Factor = 4973625413
        731122935711: 3 7 7 4973625413
       7311229357111 -> Max Prime Factor = 12939061
       7311229357111: 547 1033 12939061
18446744073709551610 -> Max Prime Factor = 1504703107
18446744073709551610: 2 5 23 53301701 1504703107
18446744073709551611 -> Max Prime Factor = 287630261
18446744073709551611: 11 59 98818999 287630261
18446744073709551612 -> Max Prime Factor = 2147483647
18446744073709551612: 2 2 3 715827883 2147483647
18446744073709551613 -> Max Prime Factor = 364870227143809
18446744073709551613: 13 3889 364870227143809
18446744073709551614 -> Max Prime Factor = 649657
18446744073709551614: 2 7 7 73 127 337 92737 649657
18446744073709551615 -> Max Prime Factor = 6700417
18446744073709551615: 3 5 17 257 641 65537 6700417