Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.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 为什么这个素数分解算法给出了正确的答案,即使存在缺陷?_C_Algorithm_Primes_Prime Factoring - Fatal编程技术网

C 为什么这个素数分解算法给出了正确的答案,即使存在缺陷?

C 为什么这个素数分解算法给出了正确的答案,即使存在缺陷?,c,algorithm,primes,prime-factoring,C,Algorithm,Primes,Prime Factoring,我遇到的问题是: 数字600851475143中最大的素因子是什么 该程序用于查找答案,使用C: #include<math.h> // for remainder because % does not work with double or floats #include<stdio.h> main() { double x=600851475143,y=3.0; while(x!=y) // divi

我遇到的问题是:

数字600851475143中最大的素因子是什么

该程序用于查找答案,使用C:

#include<math.h> // for remainder because % does not work with double or floats
#include<stdio.h>  
main()
{
    double x=600851475143,y=3.0;
    while(x!=y)                         // divide until only the number can divide itself
    {
        if(remainder((x/y),1)==0.0)     // if x is divisible by y which means it is a factor then do the magic
        {
            x=x/y;                      // divide the number x by y thereby reducing one constituent factor
        }
        y=y+2;                          // add 2 simply because only odd numbers can be prime and hence only prime numbers can be prime factors
    }
    printf("%lf",y);                    // do the printing magic
}
我想问你的问题是,我试图用所有奇数检查并除以x,但请注意,并非所有奇数都不是素数,算法中的这个缺陷应该会导致答案错误,因为实际上我应该检查素数因子而不是奇数因子

600851475143 = 71 * 839 * 1471 * 6857
令人惊讶的是,这个程序给出的答案是正确的,我检查了答案


我该怎么想呢?它没有意义。

注意算法中有3个缺陷:

2也是一个素数 它可以将非素数和奇数分开,比如9 它不会像您对27这样的数字所期望的那样,多次除以素数。 根据这些,我们可以得出结论,如果以下两个条件适用,则断开的算法将产生正确的答案:

输入的数字是奇数,因此跳过2并不重要 设数字为n=p1*p2*..*p_k,其中p_i都是素数。每个j=i:p_i!=佩吉。在这里,它意味着实际上每个素数只作为输入数的一个因子一次,从而避免了问题2+3。问题2——避免的原因很简单,问题3之所以被避免,是因为你已经用所有相关的素数因子除以了这个数,所以对于每个m=p_i1*…*p_ic,因为这个数已经被所有素数因子除以了-p_i1,…p_ic,你将无法用m除以它。
注意:该算法有3个缺陷:

2也是一个素数 它可以将非素数和奇数分开,比如9 它不会像您对27这样的数字所期望的那样,多次除以素数。 根据这些,我们可以得出结论,如果以下两个条件适用,则断开的算法将产生正确的答案:

输入的数字是奇数,因此跳过2并不重要 设数字为n=p1*p2*..*p_k,其中p_i都是素数。每个j=i:p_i!=佩吉。在这里,它意味着实际上每个素数只作为输入数的一个因子一次,从而避免了问题2+3。问题2——避免的原因很简单,问题3之所以被避免,是因为你已经用所有相关的素数因子除以了这个数,所以对于每个m=p_i1*…*p_ic,因为这个数已经被所有素数因子除以了-p_i1,…p_ic,你将无法用m除以它。
它之所以有效,是因为您的数字没有重复因子

600851475143 = 71 * 839 * 1471 * 6857

例如,请尝试使用1573499 23*37*43*43。

因为您的数字没有重复因子,所以它有效

600851475143 = 71 * 839 * 1471 * 6857

例如,请尝试使用1573499 23*37*43*43。

由于其他人都在告诉您程序有什么问题,我将给出一个使用试除法分解整数的正确算法:

function factors(n)
    f, fs := 2, []
    while f * f <= n
        if n % f == 0
            append f to fs
            n := n / f
        else f := f + 1
    append n to fs
    return fs
这解决了代码中的两个问题。首先,它正确地确定了2的因素。其次,它返回所有具有多重性的因子

回答你关于除以非素数的问题:这是一个性能问题,而不是正确性问题。由于试验因子的测试顺序是递增的,因此在测试其组成素数时,任何复合因子都已经从被分解的数字中移除。这意味着用合成除法是无用的,但不会影响结果

当然,在处理整数时,千万不要使用浮点运算。在C语言中,一旦超过长整数,您可能需要切换到库


对于整数的因式分解,有比试用除法更好的算法,也有比上面所示更好的实现试用除法的方法。但这是一个很好的起点。当你准备好阅读更多内容时,我谦虚地在我的博客上推荐这篇文章。

因为其他人都在告诉你你的程序出了什么问题,我将给出一个使用试除法分解整数的正确算法:

function factors(n)
    f, fs := 2, []
    while f * f <= n
        if n % f == 0
            append f to fs
            n := n / f
        else f := f + 1
    append n to fs
    return fs
这解决了代码中的两个问题。首先,它正确地确定了2的因素。其次,它返回所有具有多重性的因子

回答你关于除以非素数的问题:这是一个性能问题,而不是正确性问题。由于试验因子的测试顺序是递增的,因此在测试其组成素数时,任何复合因子都已经从被分解的数字中移除。这意味着用合成除法是无用的,但不会影响结果

当然,在处理整数时,千万不要使用浮点运算。在C语言中,一旦超过长整数,您可能需要切换到库

对于整数的因式分解,有比试用除法更好的算法,也有比上面所示更好的实现试用除法的方法。但这使
这是一个好的开始。当你准备好更多的时候,我谦虚地在我的博客上推荐这篇文章。

如果测试的数字是偶数,那么程序将永远运行。x总是偶数,y总是奇数,所以x==y永远不会为真

如果测试的数字是奇数素数或不同奇数素数的乘积,则循环将找到除最后一个素数因子以外的所有素数因子并除以这些素数因子,直到只剩下最大的素数因子,当y等于该最大素数因子时,循环将退出,并打印最大的素数因子

有趣的情况是,当测试的数字具有奇数素数的平方、立方等因子时。循环将找到奇数素数因子并除以它们,但例如,如果3^2是一个因子,它将除以3,留下一个因子3。到底发生了什么取决于主要因素。如果只有一个素数平方因子p^2,程序将不会结束。如果有一个立方体或两个正方形p^3或p^2 q^2,则结果将是错误的剩余因子p^2或pq,除非该数字的素数因子大于该因子

示例:3^2 x 5^2 x 13:找到因子3、5和13,然后打印15,这是错误的。
示例:3^2 x 5^2 x 17:找到因子3、5和15,然后打印17,这恰好是正确的

如果测试的数字为偶数,则程序将永远运行。x总是偶数,y总是奇数,所以x==y永远不会为真

如果测试的数字是奇数素数或不同奇数素数的乘积,则循环将找到除最后一个素数因子以外的所有素数因子并除以这些素数因子,直到只剩下最大的素数因子,当y等于该最大素数因子时,循环将退出,并打印最大的素数因子

有趣的情况是,当测试的数字具有奇数素数的平方、立方等因子时。循环将找到奇数素数因子并除以它们,但例如,如果3^2是一个因子,它将除以3,留下一个因子3。到底发生了什么取决于主要因素。如果只有一个素数平方因子p^2,程序将不会结束。如果有一个立方体或两个正方形p^3或p^2 q^2,则结果将是错误的剩余因子p^2或pq,除非该数字的素数因子大于该因子

示例:3^2 x 5^2 x 13:找到因子3、5和13,然后打印15,这是错误的。
示例:3^2 x 5^2 x 17:找到因子3、5和15,然后打印17,这恰好是正确的

算法不正确并不意味着它总是给出错误的结果。就像程序崩溃不需要未定义的行为一样。顺便说一下,您最好避免使用浮点数来解决与整数相关的问题。使用if x%y==0检查x是否可被y整除。最重要的是:格式化您的代码。什么都没有-只是在大多数平台上使用ints在这种情况下不起作用,OP可能不知道这一点。@xabhisan:做得好,但使用int64_t比切换到浮点更合适,这带来了一系列完全不同的问题。代码还有更多的问题:12是质数。2应该考虑两次的因素呢?例如,对于数字27,质数3应该被计算为3times@xabhisan嗯,即使一个坏了的钟一天也能显示两次正确的时间。这个算法也是如此。一个不正确的算法并不意味着它总是给出错误的结果。就像程序崩溃不需要未定义的行为一样。顺便说一下,您最好避免使用浮点数来解决与整数相关的问题。使用if x%y==0检查x是否可被y整除。最重要的是:格式化您的代码。什么都没有-只是在大多数平台上使用ints在这种情况下不起作用,OP可能不知道这一点。@xabhisan:做得好,但使用int64_t比切换到浮点更合适,这带来了一系列完全不同的问题。代码还有更多的问题:12是质数。2应该考虑两次的因素呢?例如,对于数字27,质数3应该被计算为3times@xabhisan嗯,即使一个坏了的钟一天也能显示两次正确的时间。我不同意这种算法。例如27,它会给你答案9,这不是一个主要因素。我确实同意,通过解决问题3,这就成了一个无问题。你认为当且仅当n=p时该方法才有效是错误的₁*P₂*...*Pₖ p在哪里ᵢ 是不同的素数。该声明在only if部分是错误的,因为该方法适用于某些非该形式的数字,例如1161=27*43得到正确的结果43。这个例子表明你的主张是错误的。@Thomash我不同意。例如27,它会给你答案9,这不是一个主要因素。我确实同意通过解决问题3,这将成为一个无问题。你认为我是错的
当且仅当n=p时thod有效₁*P₂*...*Pₖ p在哪里ᵢ 是不同的素数。该声明在only if部分是错误的,因为该方法适用于某些非该形式的数字,例如1161=27*43得到正确的结果43。这个例子表明你的说法是错误的。我希望看到这个算法在fed 9时锁定。@Vesper完全正确!但在225上,is产生一个非素数因子,并停止。我希望看到这个算法在输入9时锁定。@Vesper!但在225上,is产生一个非素因子,并停止。