Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 大于int数的素数分解_C_Int_Primes_Long Integer - Fatal编程技术网

C 大于int数的素数分解

C 大于int数的素数分解,c,int,primes,long-integer,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, 10000

这个程序用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;
}

这个程序适用于小于108的数字。但我的问题是,是否有办法让这个程序甚至适用于1012这样的数字。我知道int是不够的,但当我尝试使用long int时,它就不起作用了。我还听说了一些关于malloc的事情,但我一直未能理解它。

您可以使用long-long。但是,真正的问题可能是,对不适合正常整数的数字进行因式分解需要很长时间。例如,如果您试图对10^12范围内的素数进行因式分解,则必须进行大约10^6次的除法


关于malloc的事情根本帮不了你解决这个问题,因为更大的值需要更长的时间才能分解。因此,如果您想知道malloc是如何工作的,我建议您单独提出一个问题。

下面是使用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;
}
这运行较慢,但合理。通过将unsigned long long替换为某些编译器支持的uint128\t,可以在某些系统上进一步实现这一点:

typedef unsigned __int128 uint128_t;
并将未签名的long声明升级为未签名的long-long。您需要为uint128\t类型提供数字打印例程,因为printf不会直接处理它们。我用上面的代码尝试了这一点,它成功了:

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

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

但我从来没有看到它在运行时完成超过一个数字

分解大数通常需要比简单的试算法更微妙的方法。以下是一种可能的大纲方法:

把所有的素数列出来,比如说25000个。 使用该列表删除25000以下的所有基本因子。 如果余数大于1,则使用Miller-Rabin测试或类似测试检查余数是否为素数。 如果余数是素数,那么您已经找到了最后一个因子。 如果余数不是素数,那么必须对其进行因式分解。恐怕这将不可避免地很慢。 使用类型unsigned long long作为数字和素数因子将使您以计算时间更长为代价达到1019

但是请注意,定义具有自动存储的大型本地阵列可能会导致问题,特别是当其大小达到8兆字节时,就像类型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;
}

给定32位系统,int和long都可以包含最多为2^32/2-1的数字。您可以使用64位类型的long long,或者更好的是使用uint64\t,它给出2^64-1。整数值的范围通常在每本初级C编程书的第一章中都有解释。您想看看C整数类型。@Lundin Win64也有32位int和long;后者在C:-中表示:1000000个分区与当前x86或ARMv7/8A CPU不是一个真正的问题。啊,我没有检查代码,因为这与问题无关。我们不知道他手头有多少CPU,速度有多快。让我们等待下一个问题:我如何加快代码速度?如果超过64位,实际素数的计算时间将非常长。您可能需要补充一点,您需要使用2,3,5,7,11,13,17,19,23,29,31运行Miller-Rabin测试,和37以避免低于2^64的误报。@chqrlie存在一组只有7个碱基的碱基,使得MR在n上具有确定性
#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;
}