递归C函数计算数字之和

tzdcorbm  于 2023-11-16  发布在  其他
关注(0)|答案(6)|浏览(139)

我写了一个递归计算数字之和的C程序,我的问题是是否有其他方法,最好是更快的方法,可以完成这个过程。
这是我的代码,也许我可以避免使用prototype函数,但我不知道这是否会使它更快。

#include <stdio.h>

int sum(int);

int main() {
    int i;
    scanf("%d\n", &i);
    printf("%d", sum(i));
}

int sum(int x) {
    int res;
    if (x > 9) {
        res = (sum(x % 10) + sum(x / 10));
    } else {
        res = x;
    }
    return res;
}

字符串

6tr1vspr

6tr1vspr1#

正如在注解中提到的,使用递归是没有意义的。这里有一个非常简单的迭代版本,它应该更快:

int sum(int x) {
    int res = 0;
    while (x) {
        res += x % 10;
        x /= 10;
    }
    return res;
}

字符串
请注意,这假设x是非负的。

ioekq8ef

ioekq8ef2#

  • 递归永远不会导致更快的代码。它经常导致更慢或更难阅读的bug代码。它还经常增加峰值RAM消耗。所有这些都是绝对没有回报的。
  • 除了递归之外,这里最显著的瓶颈是除法。大多数CPU执行除法的速度很慢。

因此,明显的改进方法是摆脱上述两种方法。如果你知道目的是对数字求和,你可以把输入作为一个字符串。

int sum=0;
for(size_t i=0; str[i]!='\0'; i++)
  sum += str[i] - '0';

字符串
根据CPU的不同,这应该比你目前拥有的快 * 很多倍。

66bbxpm5

66bbxpm53#

我的问题是,是否有任何其他方法,最好是更快的方法,可以完成这一程序。
不要使用递归。
递归并不能使代码更快,它使某些算法更容易实现,因为你不必自己做簿记。
快速排序之所以快,并不是因为它是递归的;它之所以快,是因为它通过将列表划分为部分排序的子列表,最大限度地减少了比较和交换的次数。它通常以递归的方式实现,因为它比维护自己的堆栈更容易。
相反,递归斐波纳契实现是非常慢的,因为你要多次计算相同的项(对于大的N,最多数千次)。
Lundin和Tom的解决方案是更好的方法。
现在,已经说过了所有这些,没有一个int会有超过10位的数字,所以各种算法之间的增量几乎是不可测量的;只有当你要在你的程序中调用这个函数 * 数千次 * 时,这才是一个问题。
也许我可以避免原型函数,但我不知道这是否会使它更快。
声明的形式对代码的运行时性能没有影响。

h5qlskok

h5qlskok4#

递归对这个函数没有帮助,在这种情况下效率很低。
下面是一个更简单的版本,可以处理正值和负值:

#include <stdlib.h>

int sum(int x) {
    int res = 0;
    while (x) {
        res += x % 10;
        x /= 10;
    }
    return abs(res);
}

字符串

ig9co6j1

ig9co6j15#

虽然其他答案是正确的,但 * 一些 * C编译器 * 可能 * 实现了尾调用优化,并自动将尾递归代码转换为迭代代码。
如果我们添加一个额外的累加器参数来累加函数的运行和,我们就可以实现尾递归。

int sum(int x, int acc) {
    if (x == 0) return acc;
    
    return sum(x / 10, acc + x % 10);
}

int main(void) {
    int i;
    scanf("%d\n", &i);
    printf("%d", sum(i, 0));
}

字符串
我们可以通过定义一个接受累加器的sum_tailrec函数,然后让sum调用该函数,将累加器初始化为零来隐藏这个细节。

mlmc2os5

mlmc2os56#

在我看来,你的递归函数应该是

unsigned sum(unsigned x)
{
    return x > 0
        ? sum(x / 10) + x % 10
        : 0;
}

字符串
因为你知道除法的余数就是数字本身,只要把它加到数字的和上,而不加最后一位数字。在某个时候,除法将是0,所以算法是有保证的。

相关问题