编写一个程序,从键盘读取整数,并在输出上写入 n 的除数之和(除了它本身)。
我创建了一个求除数之和的方法。使用 while 语句,我最多可以让用户输入 10 个整数,直到 EOF。在 while 语句中,我有 sum = sum_divisor 的输出并打印出 sum。
如果我输入 0 0 0 4 5 6 12 那么输出应该是 0 0 0 3 1 6 16。 我得到的输出是 0 0 0 3 4 10 26。我怎样才能使它不将 sum_divisor 添加到之前的总和中?
#include <stdio.h>
int sum_divisor(int x);
int main()
{
int x;
int sum;
printf("Enter up to 10 positive integer ending with EOF:\n");
while((scanf("%d",&x)) != EOF){
sum = sum_divisor(x);
printf("%d ", sum);
}
return 0;
}
int sum_divisor(int x){
int i;
int sum;
if(x<= 0){
sum = 0;
}
else{
for(i=1;i<x;++i)
{
if(x%i==0)
sum += i;
}
}
return sum;
}
最佳答案
您应该在函数中将 sum
初始化为零。否则,它将被设置为某个任意值,并且 else
block 将具有任意结果。
换句话说,改变:
int sum;
进入:
int sum = 0;
当然,完成此操作后,对于 x
小于 1 的情况,无需显式执行任何操作。此外,最初的 if 是多余的,因为当 x 小于 1 时,for 主体不会执行,因此您可以逃脱像这样:
int sumDivisors (int x) {
int i, sum = 0;
for (i = 1 ; i < x; i++) {
if ((x % i) == 0) {
sum += i;
}
}
return sum;
}
顺便说一句,您在没有初始化的情况下实际看到的值正在累积:
0 -> 0
0 -> 0
0 -> 0
3 -> 3
1 -> 4
6 -> 10
16 -> 26
这几乎可以肯定是因为对函数的每次调用都为堆栈帧重用相同的内存,包括变量 sum
,因此 sum
只是添加到每个time(传入的参数大于1)。
但是,这只是实现的一个产物,它不受标准保证,该标准在 C11 6.7.9 Initialization/10
中明确说明:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
换句话说,不要依赖于此。
而且,除此之外,这是一个数学问题,如果一个数 n
能被 a
整除,它也会被整除由不适用
。您可以利用这一点来提高代码的效率(不过,与所有优化一样,您应该测量,而不是猜测)。
由于您将数字本身作为除数进行折扣,因此必须将除数 1
视为特殊情况。您还必须将完全平方视为特殊情况,这样就不会两次添加平方根。
以下代码将是一个很好的起点:
int sumDivisors (int x) {
int i, sum;
// Always return zero for -inf..1 inclusive.
if (x < 2)
return 0;
// Otherwise, 1 is factor, search for others
// up to but NOT including sqrt(x).
for (i = 2, sum = 1 ; i * i < x; i++) {
if ((x % i) == 0) {
sum += i;
sum += x / i;
}
}
// Add in sqrt(x) ONCE for a perfect square.
if (i * i == x)
sum += i;
return sum;
}
关于c - 除数之和(除了它本身),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33489808/