C中的主要因素

时间:2018-06-08 22:01:36

标签: c primes algebra sqrt

我遇到了这个打印给定数字的所有主要因素的有效程序:

# include <stdio.h>
# include <math.h>

// A function to print all prime factors of a given number n
void primeFactors(int n)
{
    // Print the number of 2s that divide n
    while (n%2 == 0)
    {
        printf("%d ", 2);
        n = n/2;
    }

    // n must be odd at this point.  So we can skip 
    // one element (Note i = i +2)
    for (int i = 3; i <= sqrt(n); i = i+2)
    {
        // While i divides n, print i and divide n
        while (n%i == 0)
        {
            printf("%d ", i);
            n = n/i;
        }
    }

    // This condition is to handle the case when n 
    // is a prime number greater than 2
    if (n > 2&&n%2!=0)
        printf ("%d ", n);
}

/* Driver program to test above function */
int main()
{
    int n = 315;
    primeFactors(n);
    return 0;
}

输出为3 3 5 7.这是完美的。

但我对这个算法感到困惑。 sqrt()返回一个浮点值。如果它在printf中以整数格式显示,则返回一些随机的大数字。如果是这种情况,for循环中的条件应该失败,因为sqrt()作为整数返回一个随机数。有人可以解释一下吗?

另外,有人可以验证这个吗?这个算法错误地写在geeksforgeeks网站上,好像(n> 2)而不是if(n> 2&amp; n!= 0),这是我添加的。有人请验证这个算法。提前致谢。

3 个答案:

答案 0 :(得分:6)

如果您尝试打印sqrt(n) 的值,就好像那样它是一个整数:

printf("sqrt(n) = %d\n", sqrt(n)); // Don't do this

然后你有未定义的行为。 sqrt()会返回double类型的结果。编译器不知道(或者不需要知道)参数的预期类型。您可以通过正确类型的参数。上面对printf的调用具有未定义的行为。

在其他上下文中,表达式的类型和期望类型是明确的,语言需要隐式转换。特别是,在表达式i <= sqrt(n)中,in的类型为int,参数nint转换为{ {1}}(double的参数类型)sqrt() i , and the value of int is also converted from double`。结果可能与您的预期相符。

顺便说一下,这个:

to

可能效率低下。 for (int i = 3; i <= sqrt(n); i = i+2) ... 函数相对昂贵,并且会在循环的每次迭代中调用它。 (在某些情况下,预计算sqrt是一个很好的解决方案,但此处sqrt(n)的值可以在循环内发生变化。)

另一种选择是:

n

避免了浮点运算的复杂性(但考虑for (int i = 3; i*i <= n; i += 2) ... 是否会溢出)。

(如果C在标准库中有一个整数平方根函数会很好,但它不会。)

答案 1 :(得分:2)

据我所知,您将DOMContentLoaded传递给float函数printf()说明符是%d。这是undefined behavior

N1570 7.21.6.1第9段:

  

...如果任何参数不是相应的正确类型   转换规范,行为未定义。

这就是你看到垃圾价值的原因。由于C不是strictly typed language,编译器可能会警告您,但不会出现编译时或运行时错误。

enter image description here

它已成功编译,但其输出为integer。再说一遍,这是UB。

答案 2 :(得分:0)

其他人建议预先计算整数平方根,但您需要小心根据需要重新计算它。对于主循环,我会使用类似的东西:

// n must be odd at this point.  So we can skip 
// one element (Note i = i +2)
int limit = isqrt(n);  // Calculate integer square root.
for (int i = 3; i <= limit; i = i+2)
{
    // While i divides n, print i and divide n
    if (n % i == 0)
    {
        printf("%d ", i);
        n = n / i;

        while (n%i == 0)
        {
            printf("%d ", i);
            n = n / i;
        }

        // Recalculate limit as n has changed.
        limit = isqrt(n);
    }
}

这只会在测试的数字发生变化时重新计算平方根。我使用isqrt(n)来表示执行实际计算的函数。在我自己的代码中,我使用Newton-Raphson,但还有其他可能的方法。

最后的测试可以简化为:

// This condition is to handle the case when n 
// is a prime number greater than 2
if (n > 1)
{
    printf ("%d ", n);
}

最多有一个素数因子大于数字的平方根。在所有较小的素因子被分割出来之后,唯一的因素(如果存在)将是剩余因素。