查找从2到较大范围的所有友好数字对-错误的输出

时间:2018-08-06 16:21:20

标签: c function output

我正在尝试编写一个函数,该函数查找从2到给定上限范围内的所有友好数字。

我编写了一个函数,该函数查找给定数字的除数之和。

我还编写了一个函数,该函数使用以下事实:如果 num1 的除数之和为 S(num1),而 num2 = s(num1)- num1 具有相同的除数,那么num1和num2是友好数字。

这是我的代码:

#define _CRT_SECURE_NO_WARNINGS

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

void amicableNumbers(int n);
int findSumOfDevisors(int num);

void main() {
    int upperRange;

    printf("enter the value for upper range: ");
    scanf("%d", &upperRange);
    printf("the amicable numbers between 2 and %d:\n", upperRange);
    amicableNumbers(upperRange);
}

void amicableNumbers(int n) {
    int sum, sum2, i;

    for (i = 2; i <= n; i++) {
        sum = findSumOfDevisors(i);
        if (sum > i && sum <= n) {
            sum2 = findSumOfDevisors(sum);
            if (sum2 == i)
                printf("%d and %d \n", i, sum);
        }
    }
}

int findSumOfDevisors(int num) {
    int sum = 1, i, n;

    n = (int)sqrt((double)num);
    for (i = 2; i <= n; i++) {
        if ((n % i) == 0) {
            sum += i;
            sum += n / i;
        }
    }
    return sum;
}

但是,当我运行它时,我得到了错误的输出。例如,对于upperRange 301,我发现2-301范围内没有任何友好数字。

  

可和数字是两个不同的数字,因此彼此相关,以使每个数字的适当除数之和等于另一个数字。例如,对220和284是友好的数字。 220的适当除数之和为1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284,而284的适当除数之和为1 + 2 + 4 + 71 + 142 = 220。

     

除数本身以外,数字的适当除数是该数字的正因数。

4 个答案:

答案 0 :(得分:3)

OP的findSumOfDevisors()有麻烦。也许其他代码也可以。

  1. sqrt()不一定要给出准确的平方根-一些较弱的实现可能会导致值刚好在预期答案之上或之下。加上(int)会截断分数,答案如123.999999999 ...变成123而不是124。在任何情况下,此处都不需要精度问题的浮点数学。

    仅建议使用整数数学:

    // n =(int) sqrt((double)num);
    // for (i = 2; i <= n; i++)
    for (i = 2; i <= num/i; i++)
    
  2. 避免溢出。

    // for (i = 2; i*i <= num; i++)  `i*i` may overflow.
    for (i = 2; i <= num/i; i++)
    
  3. 将相同的值累加两次?当除数和商相同时,代码会将它们都计算在内。我只希望一个。

    sum += i;
    // sum += n / i;
    if (i != n/i) sum += n/i;
    
  4. 出于完整性考虑,我希望findSumOfDevisors(0)findSumOfDevisors(1)返回0,而不是像OP的代码一样返回1。负数是另一个未解决的问题。

    // int sum = 1;
    int sum = num > 1;
    
  5. 使用昂贵的/, %还是2换1?考虑以下代码。 %/可能会调用一些昂贵的余数和除法计算。然而,对于许多优秀的编译器而言,num/inum % i会导致发出的代码在一次操作中同时计算两个代码。最好为清晰起见编写代码,但是如果您需要考虑持久性,请研究一个好的优化编译器的结果。

    for (i = 2; i < num/i; i++) {
      if (num%i == 0) {
    

答案 1 :(得分:2)

不建议在findSumOfDivisors中使用浮点运算,请尝试以下方法:

int findSumOfDivisors(int num) {
    int sum = 1, div, i;

    for (i = 2; i <= (div = num / i); i++) {
        if (num % i == 0) {
            sum += i;
            if (i == div)
                break;
            sum += div;
        }
    }
    return sum;
}

此外,您的amicableNumbers函数太复杂了,您应该简单地测试一下该和的除数之和是否为原始数:

void amicableNumbers(int n) {
    int sum, i;

    for (i = 2; i <= n; i++) {
        sum = findSumOfDivisors(i);
        if (sum > i && sum <= n && findSumOfDivisors(sum) == i)
            printf("%d and %d\n", i, sum);
        }
    }
}

最后,没有参数的main的原型是int main(void),您应该测试scanf()的返回值并从0返回main

这是改进版:

#include <stdio.h>

int findSumOfDivisors(int num) {
    int sum = 1, div, i;

    for (i = 2; i <= (div = num / i); i++) {
        if (num % i == 0) {
            sum += i;
            if (i == div)
                break;
            sum += div;
        }
    }
    return sum;
}

void amicableNumbers(int n) {
    int sum, i;

    for (i = 2; i <= n; i++) {
        sum = findSumOfDivisors(i);
        if (sum > i && sum <= n && findSumOfDivisors(sum) == i)
            printf("%d and %d\n", i, sum);
        }
    }
}

int main(void) {
    int upperRange;

    printf("enter the value for upper range: ");
    if (scanf("%d", &upperRange) == 1) {
        printf("the amicable numbers between 2 and %d:\n", upperRange);
        amicableNumbers(upperRange);
    }
    return 0;
}

答案 2 :(得分:1)

您的findSumOfDevisors函数错误。此外,IMO sqrt()函数对于性能而言是压倒性的。相反,您应该使用i <= num / 2

int findSumOfDevisors(int num)
{
    int sum = 1, i,n;

    //n =(int) sqrt((double)num);
    for (i = 2; i <= num / 2; i++)
    {
        if ((num % i) == 0)
        {
            sum += i;
        }
    }
    return sum;
}

此外,if (sum > i && sum <= n)可以简化为i < sum

答案 3 :(得分:0)

问题出在此功能

int findSumOfDevisors(int num)

您要输入num而不是n是输入错误 正确的功能是

int findSumOfDevisors(int num)
{
int sum = 1, i,n;

 n =(int) sqrt((double)num);
for (i = 2; i <= n; i++)
{
    if ((num % i) == 0)
    {
        sum += i;
        sum += num / i;
    }
}
return sum;
}