比int更大数的素数因子分解

时间:2016-11-07 15:39:33

标签: c int primes long-integer

该程序对C中的数字进行素数分解。

#include <stdio.h>

int main(void) {
    int number, i, p, n, factors, count;
    int numbers[1000000];
    int counter = 0;
    char text[100000]; 

    for (count = 0; count < 1000000; count++) {
        fgets(text, 10000000, stdin);
        if (sscanf(text, "%d", &number) == 1) {
            if (number == 0)
                break;
            numbers[count] = number;
        } else {
            numbers[count] = 0;
        }
    }
    counter = 0; 
    for (i = 0; i < count; i++) {
        if ((numbers[i] < 0) || (numbers[i] == 0)) {
            fprintf(stderr, "Error: Wrong Input!\n");
            return 100;
            break;
        }
        number = numbers[i];
        printf("Prime factorization of nubmer %d is:\n", number);
        factors = 0;
        for (p = 2; p * p <= number; p += 1 + (p & 1)) {
            if (number % p == 0) {
                n = 0;
                factors++;
                do {
                    number /= p;
                    n++;
                } while (number % p == 0);
                if (n == 1) {
                    printf("%d ", p);
                    ++counter;
                } else 
                    printf("%d^%d ", p, n);
                ++counter;

                if (count > 0 && number != 1) 
                    printf("x ");
            }
        }
        if (factors == 0 || number != 1)
            printf("%d", number);
        printf("\n");
    }
    return 0;
}

此程序适用于小于10 8 的数字。但我的问题是,如果有一种方法可以使这个程序甚至对于像10 12 这样的数字。我知道int不够,但是当我尝试使用long int时,它没有用。我也听说过malloc的一些内容,但我一直未能实现(理解)它。

4 个答案:

答案 0 :(得分:1)

对大数字进行因子分解通常需要比简单的试验分割更微妙的方法。这是一个可能的大纲方法:

  1. 列出所有素数,例如25,000。
  2. 使用该列表删除低于25,000的所有素数因子。
  3. 如果有剩余的&gt; 1然后用Miller-Rabin测试或类似的方法检查剩余部分是否为素数。
  4. 如果剩余部分是素数,那么你找到了最后一个因素。
  5. 如果余数不是素数,那么你将不得不将其分解。那恐怕会慢得多。

答案 1 :(得分:0)

你可以使用很长时间。但是,真正的问题可能是,需要花费很长时间对数字进行因子分解,而这些因素并不适合普通的数据。例如。你试图将10 ^ 12范围内的素数分解,那么你将不得不做大约10 ^ 6个分数。

关于malloc的事情根本不会帮助你解决这个问题,因为更大的价值观需要更长的时间来分解。所以,如果你想知道malloc是如何工作的,我建议为此开一个单独的问题。

答案 2 :(得分:0)

以下是使用unsigned long long对代码进行的返工。 (我抛出文件的东西,以保持这个最小的例子。)这是否适用于您的目的取决于您的系统如何定义long long(在我的系统上它的64位)。我还重新编写了输出格式以兼容Unix dc命令的后缀表示法,因此我可以轻松检查结果是否正确:

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

int main() {

    unsigned long long large = 18446744073709551615ULL; // 2^64 - 1

    for (unsigned long long counter = large - 1000; counter < large; counter++) {

        unsigned long long number = counter;

        printf("Prime factorization of %llu is:", number);

        unsigned long factors = 0;

        for (unsigned long long p = 2; p * p <= number; p += 1 + (p & 1)) {

            if (number % p == 0) {
                factors++;

                unsigned long n = 0;

                do {
                    number /= p;
                    n++;
                } while (number % p == 0);

                if (n == 1) {
                    printf(" %llu", p);
                }
                else {
                    printf(" %llu %lu ^", p, n);
                }

                if (number != 1 && factors > 1) {
                    printf(" *");
                }
            }
        }

        if (factors == 0 || number != 1) {
            factors++;

            printf(" %llu", number);
        }

        if (factors > 1) {
            printf(" *");
        }

        printf("\n");
    }

    return 0;
}

SAMPLE OUTPUT

% ./a.out
Prime factorization of 18446744073709550615 is: 5 563 * 751 * 8725722280871 *
Prime factorization of 18446744073709550616 is: 2 3 ^ 3 * 41 * 7523 * 8243 * 14479 * 20879 *
Prime factorization of 18446744073709550617 is: 79 557 * 419215600611539 *
Prime factorization of 18446744073709550618 is: 2 2298974999 * 4011949691 *
Prime factorization of 18446744073709550619 is: 3 3 ^ 1008659 * 677347590683 *
Prime factorization of 18446744073709550620 is: 2 2 ^ 5 * 7 * 149 * 233 * 3795329598449 *
Prime factorization of 18446744073709550621 is: 11 23 * 72912031911895457 *
Prime factorization of 18446744073709550622 is: 2 3 * 479909 * 6406334004193 *
Prime factorization of 18446744073709550623 is: 3421377637 5391612979 *
Prime factorization of 18446744073709550624 is: 2 5 ^ 61 * 593 * 1699 * 9379762391 *
Prime factorization of 18446744073709550625 is: 3 5 4 ^ * 13 * 756789500459879 *
Prime factorization of 18446744073709550626 is: 2 3743461 * 2463862195133 *
Prime factorization of 18446744073709550627 is: 7 1283 * 4339 * 627089 * 754877 *
Prime factorization of 18446744073709550628 is: 2 2 ^ 3 2 ^ * 101 * 293 * 42751 * 405025111 *
Prime factorization of 18446744073709550629 is: 17 43 * 613 * 66457 * 619442699 *
...

这样运行速度较慢但合理。您可以通过将unsigned long long替换为某些编译器支持的uint128_t来在某些系统上进一步推动这一点:

typedef unsigned __int128 uint128_t;

(然后将unsigned long声明提升至unsigned long long。)您需要为uint128_t类型提供数字打印例程printf() isn&#39;我会直接处理它们。我用上面的代码尝试了这个并且它有效:

Prime factorization of 340282366920938463426481119284349108124 is: 2 2 ^ 31 * 6131 * 7654271 * 21163829 * 21491837 * 128562653437 *

% dc
2 2 ^ 31 * 6131 * 7654271 * 21163829 * 21491837 * 128562653437 * p 
340282366920938463426481119284349108124

但我在运行它时从未看到它完成多个数字!

答案 3 :(得分:0)

unsigned long long使用number类型,素数因子将以更长的计算时间为您带来10 19

但请注意,定义具有自动存储的大型本地阵列可能会导致问题,尤其是当它达到8 MB的大小时,类型为unsigned long long的情况(此类型至少为64位宽) 。从堆中分配它更安全。

以下是代码的改编版本:

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

#define NUMBER_MAX  1000000

int main(void) {
    unsigned long long *numbers;
    unsigned long long number, p;
    int i, n, factors, count;
    char text[100]; 

    numbers = calloc(NUMBER_MAX, sizeof(*numbers));
    if (numbers == NULL) {
        printf("cannot allocate number array\n");
        return 1;
    }

    for (count = 0; count < NUMBER_MAX; count++) {
        if (!fgets(text, sizeof text, stdin)) {
            break;
        }
        if (sscanf(text, "%llu", &number) == 1 && number > 0) {
            numbers[count] = number;
        } else {
            fprintf(stderr, "Error: Wrong Input!\n");
            return 100;
        }
    }
    for (i = 0; i < count; i++) {
        number = numbers[i];
        printf("Prime factorization of nubmer %llu is:\n", number);
        factors = 0;
        for (p = 2; p < 0x100000000 && p * p <= number; p += 1 + (p & 1)) {
            if (number % p == 0) {
                n = 0;
                factors++;
                do {
                    number /= p;
                    n++;
                } while (number % p == 0);
                if (n == 1) {
                    printf("%llu ", p);
                } else {
                    printf("%llu^%d ", p, n);
                }
                if (number != 1) {
                    printf("* ");
                }
            }
        }
        if (factors == 0 || number != 1) {
            printf("%llu", number);
        }
        printf("\n");
    }
    free(numbers);
    return 0;
}