【问题标题】:Finding the sum of the digits找到数字的总和
【发布时间】:2010-08-16 02:23:35
【问题描述】:

我有一个 5 位整数,比如说

int num = 23456;

如何求其位数之和?

【问题讨论】:

  • 答案是 20。
  • yup Carl.... 我想知道如何使用 C 计算它
  • @Josh,然后向我们展示您到目前为止所做的事情并询问我们一个具体问题。让我们做你的功课(或者更糟糕的是,真正的工作)在这里不会很受欢迎。
  • @Carl。谢谢你,下次我会更具体......我得到了答案。模算术是我一直在寻找的。​​span>
  • @Carl,至少在你的幽默结束时放一个笑脸:-)

标签: c algorithm math


【解决方案1】:

使用modulo operation 获取最低有效位的值:

int num = 23456;
int total = 0;
while (num != 0) {
    total += num % 10;
    num /= 10;
}

如果输入可能是负数,那么最好检查一下并反转符号。

【讨论】:

  • @马克。谢谢..这就是我要找的。​​span>
  • 我实际上并不太喜欢while (num) 之类的东西,除非num 是一个实际的布尔类型值。我认为使用if (num != 0) 更具可读性(除非您的编译器脑残,否则同样有效)。当然,我不喜欢它来否决正确的答案,只是我今天还没有咆哮,尽管咆哮是可悲的低调,但它必须这样做:-)
  • 哦,我真的没想到你会“修复”它,因为它只是我的一个宠物小毛病。所以 +1 如此亲切:-)
  • 我不太喜欢与 0 进行无用的比较。C 的成语是 while (foo) 的意思是“而 foo 不为零”,任何声称知道 C 和一样可读。顺便说一句,我们应该开始写while (...(((num!=0)!=0)!=0...!=0)???
  • do { total += num % 10; } while (num /= 10); >:)
【解决方案2】:
#include <stdio.h>

int main()
{
    int i = 23456;
    int sum = 0;

    while(i)
    {
        sum += i % 10;
        i /= 10;
    }

    printf("%i", sum);

    return 0;
}

【讨论】:

    【解决方案3】:
    int sum=0;while(num){sum+=num%10;num/=10;}
    

    如果 num 为否定,则给出否定答案,无论如何在 C99 中。

    这是作业吗?

    【讨论】:

    • 谢谢你。不是作业,与编码失去联系,所以再次学习 C。
    • 这比 C 更符合基本的数学算法。
    【解决方案4】:

    这个怎么样:

    for(sum=0 ,num=23456;num; sum+=num %10, num/=10);
    

    【讨论】:

    • 谢谢哥们。这其中的逻辑是怎样的???并且可以在没有任何控制语句的情况下计算数字的总和。
    • 逻辑类似于 Mark Byers 的回答逻辑。 And can the sum of the digits be calculated without any control statements 为什么会有人这样做?
    • 如果你对数字有一个界限,那么可能有一个很好的乘法技巧可以在没有任何控制语句的情况下获得数字的总和。
    【解决方案5】:

    如果您想要一种无需控制语句且启动效率极高的方法,请使用O(1) 而不是O(n), n = digit count 方法:

    int getSum (unsigned int val) {
        static int lookup[] = {
             0,  1,  2,  3,  4,  5,  6,  7,  8,  9, //     0-    9
             1,  2,  3,  4,  5,  6,  7,  8,  9, 10, //    10-   19
             2,  3,  4,  5,  6,  7,  8,  9, 10, 11, //    20-   29
             :
             9, 10, 11, 12, 13, 14, 15, 16, 17, 18, //    90-   99
             :
            14, 15, 16, 17, 18, 19, 20, 21, 22, 23, // 23450-23459
            ::
        };
        return lookup[23456];
    }
    

    :-)

    【讨论】:

    • 不幸的是它在太空中是O(2^n)。 ;-)
    【解决方案6】:

    稍微相关:如果你想要repeated digit sum,一个不错的优化是:

    if (num%3==0) return (num%9==0) ? 9 : 3;
    

    接下来是其余的代码。

    【讨论】:

      【解决方案7】:

      实际上,我回答了另一个(有点幽默)的答案,它使用了一个绝对巨大的数组来进行表格查找,但是回想一下,如果您限制表格大小,这并不是一个坏主意。

      以下函数以空间换时间。与所有优化一样,您应该在目标环境中自己分析它们。

      首先是(优雅的)递归版本:

      unsigned int getSum (unsigned int val) {
          static const unsigned char lookup[] = {
               0,  1,  2,  3,  4,  5,  6,  7,  8,  9, //   0-  9
               1,  2,  3,  4,  5,  6,  7,  8,  9, 10, //  10- 19
               2,  3,  4,  5,  6,  7,  8,  9, 10, 11, //  20- 29
               :
              18, 19, 20, 21, 22, 23, 24, 25, 26, 27  // 990-999
          };
          return (val == 0) ? 0 : getSum (val / 1000) + lookup[val%1000];
      }
      

      它基本上将数字分成三位数的分组,并针对每种可能性进行固定查找。这可以轻松处理递归深度为 7 个堆栈帧的 64 位无符号值。

      对于那些甚至不相信 少量递归的人(你应该这样做,因为普通程序甚至在没有递归的情况下会走得更深,甚至更深),你可以尝试迭代解决方案:

      unsigned int getSum (unsigned int val) {
          static const unsigned char lookup[] = {
               0,  1,  2,  3,  4,  5,  6,  7,  8,  9, //   0-  9
               1,  2,  3,  4,  5,  6,  7,  8,  9, 10, //  10- 19
               2,  3,  4,  5,  6,  7,  8,  9, 10, 11, //  20- 29
               :
              18, 19, 20, 21, 22, 23, 24, 25, 26, 27  // 990-999
          };
          unsigned int tot = 0;
          while (val != 0) {
              tot += lookup[val%1000];
              val /= 1000;
          }
          return tot;
      }
      

      这些可能比一次一位数的解决方案快三倍,代价是一千字节的数据。如果您不反对使用 10K 或 100K,您可以将速度提高到四到五倍,但您可能需要编写一个程序来生成上面的静态数组语句 :-)

      与所有优化选项一样,衡量,不要猜测!

      我自己更喜欢更优雅的递归解决方案,但我也是喜欢神秘填字游戏的类型之一。随心所欲地阅读。

      【讨论】:

      • 堆栈帧命中内存。查找表需要缓存以提高效率,然后它们会吃掉您的缓存。一个足够聪明的编译器可能会注意到这种情况下的递归等同于迭代,但这不太可能,因为您的实现甚至不是尾递归的。更喜欢小代码,这样你就不会吃掉你的 I-cache。
      【解决方案8】:
         #include <stdio.h>
        2 #include <stdlib.h>
        3
        4 #define BUFSIZE 20
        5
        6 int main(void)
        7 {
        8         int     number = 23456;
        9         char    myBuf[BUFSIZE];
       10         int     result;
       11         int     i = 0;
       12
       13         sprintf(myBuf,"%i\0",number);
       14
       15         for( i = 0; i < BUFSIZE && myBuf[i] != '\0';i++)
       16         {
       17                 result += (myBuf[i]-48);
       18         }
       19
       20         printf("The result is %d",result);
       21         return 0;
       22 }
       23
      

      这里使用 sprintf 和 ascii 数字表示的另一个想法

      【讨论】:

        【解决方案9】:
        #include<stdio.h>
        main()
        {
                         int sum=0,n;
                         scanf("%d",&n);
                         while(n){
                               sum+=n%10;
                               n/=10;
                         }
                         printf("result=%d",sum);
        }
        

        sum 是数 n 的位数之和

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-07
          • 2022-08-20
          • 1970-01-01
          • 1970-01-01
          • 2017-06-06
          • 2010-11-16
          • 1970-01-01
          相关资源
          最近更新 更多