繁体   English   中英

C素数分解(循环失败?)

[英]C prime factorization (loop failure?)

我一直在研究这段简单的代码1.5个小时,但没有发现错误。 我开始疯了;)

你们每个人只要有新的想法和观点,都可以给我一点提示,我可能在哪里出现错误? (我是C的新手)

问题是:该代码对于我输入并测试的大多数数字都可以正常工作,但是偶然地我发现了一个不起作用的数字:3486118(或55777888的整数倍),它适合于第一个循环,但是在因子2之后,它将变成一个无限循环。

这是我的代码:(非常感谢您的帮助)

// Program calculates prime factors of entered number and returns them

#include <stdio.h>

int main() {

    long int num, num_cp;
    long int product=1;

    /*prime number array up to 100.000*/
    long int prime[] = {2, 3, **[...cut out MANY numbers...]** 99971, 99989, 99991};

    printf("Please enter a positive integer:\n");
    scanf("%li", &num);//55777888 or 3486118 not working... why?
    //copy the entered number to keep the original for comparison with "product" and "break;" if equal
    num_cp=num;

    printf("prime factorization of %li:\n\n", num);

    for (int i=0; i<sizeof(prime); i++) {
        if (num_cp%prime[i]==0) {
            num_cp/=prime[i];
            product*=prime[i];
            if (product==num) {
                printf("%li\n\n", prime[i]);
                break;
            }
            printf("%li*", prime[i]);

            //If prime factor found but "product" is still not equal to "num" reset loop counter "i" to -1 (==0 in next loop)
            i=-1;
        }
    }
    printf("END");
    return 0;
}

“我一直在研究这段简单的代码1.5个小时,但没有发现错误。我开始发疯了;)”

别。 别管它。 走开,吃披萨。 在您最喜欢的电影前播放视频。 洗个澡。 力争在2048(或更高水平)上取得新的高分。 您的大脑陷入了车辙,您再也看不到代码了。 您只会看到您认为的代码。

当您精疲力尽时,然后-仅在此之后-返回并实际阅读您编写的代码。 不是您认为自己编写的代码,而是您实际编写的代码。 是的,它们是不同的。

55777888的主要因子是2·2·2·2·2·1743059,其中最后一个因子太大而无法包含在列表中。

您可以在代码中解决此问题:当乘积等于找到的素数乘积时, num_cp为1。如果在用完素数列表后num_cp大于1,则为num 如果num/num_cp小于您检查的最大素数,则可以假定num_cp的剩余值为素数。 如果不是,那么您会更早发现更多因素。

您可以通过在主循环后添加其他检查来解决此问题:

if (num_cp > 1) printf("%li\n\n", num_cp);

(如果long int是系统上的64位数字,则您仍然不安全:剩余因素可能由数组中没有的几个数字组成。)

最后:重置for循环计数器以使循环重新开始不是一个好主意。 它总是从头开始,并重新检查您已经检查过的素数。 而且这不是自然的程序流程,这使得它很难阅读。 我认为,使用while循环而不是内部if块会更自然。

编辑 :以说明:

#include <stdio.h>

int main() {
    long int num;

    /* prime number array up to 100.000 */
    long int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
    int nprime = sizeof(prime) / sizeof(*prime);

    num = 55;

    printf("%li == ", num);

    for (int i = 0; i < nprime; i++) {
        long int p = prime[i];

        if (num <= 1) break;

        while (num % p == 0) {
            num /= prime[i];
            printf("%li", p);
            if (num > 1) printf(" * ");
        }
    }

    if (num > 1) printf("%li", num);
    printf("\n");

    return 0;
}

注意事项:

  • 不用重置主循环计数器i ,而是使用while循环,它消耗了相同因子的所有重复。 如果素数p不除数,则不输入while循环,就像if子句一样。
  • 我删除了num的副本并在整个过程中使用了num ,主要是为了消除混乱。 我还删除了该product 所有素因应乘以原始数的逻辑是好的。 但这也反过来起作用:将数字除以所有质数后,剩下的就是1。无论如何,我们必须对数字进行除法。 通过删除产品,我们必须仅跟踪一个变量,而不是两个变量。
  • 我已将break条件移到最前面,因此我们早早发现了负数和0。

也就是说,您的编码方式没有错,在某些地方也许有点不寻常。

暂无
暂无

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

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