我遇到了这个打印给定数字的所有主要因素的有效程序:
# 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),这是我添加的。有人请验证这个算法。提前致谢。
答案 0 :(得分:6)
如果您尝试打印sqrt(n)
的值,就好像那样它是一个整数:
printf("sqrt(n) = %d\n", sqrt(n)); // Don't do this
然后你有未定义的行为。 sqrt()
会返回double
类型的结果。编译器不知道(或者不需要知道)参数的预期类型。您可以通过正确类型的参数。上面对printf
的调用具有未定义的行为。
在其他上下文中,表达式的类型和期望类型是明确的,语言需要隐式转换。特别是,在表达式i <= sqrt(n)
中,i
和n
的类型为int
,参数n
从int
转换为{ {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,编译器可能会警告您,但不会出现编译时或运行时错误。
它已成功编译,但其输出为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);
}
最多有一个素数因子大于数字的平方根。在所有较小的素因子被分割出来之后,唯一的因素(如果存在)将是剩余因素。