简体   繁体   English

对一个数的数字求和

[英]Sum the digits of a number

If I want to find the sum of the digits of a number, ie:如果我想找到一个数字的数字总和,即:

  • Input: 932输入: 932
  • Output: 14 , which is (9 + 3 + 2) Output: 14 ,即(9 + 3 + 2)

What is the fastest way of doing this?最快的方法是什么?

I instinctively did:我本能地做了:

sum(int(digit) for digit in str(number))

and I found this online:我在网上找到了这个:

sum(map(int, str(number)))

Which is best to use for speed, and are there any other methods which are even faster?哪种方法最适合提高速度,还有其他更快的方法吗?

Both lines you posted are fine, but you can do it purely in integers, and it will be the most efficient:你发布的两行都很好,但你可以纯粹用整数来做,这将是最有效的:

def sum_digits(n):
    s = 0
    while n:
        s += n % 10
        n //= 10
    return s

or with divmod :或使用divmod

def sum_digits2(n):
    s = 0
    while n:
        n, remainder = divmod(n, 10)
        s += remainder
    return s

Slightly faster is using a single assignment statement:稍微快一点的是使用单个赋值语句:

def sum_digits3(n):
   r = 0
   while n:
       r, n = r + n % 10, n // 10
   return r

> %timeit sum_digits(n)
1000000 loops, best of 3: 574 ns per loop

> %timeit sum_digits2(n)
1000000 loops, best of 3: 716 ns per loop

> %timeit sum_digits3(n)
1000000 loops, best of 3: 479 ns per loop

> %timeit sum(map(int, str(n)))
1000000 loops, best of 3: 1.42 us per loop

> %timeit sum([int(digit) for digit in str(n)])
100000 loops, best of 3: 1.52 us per loop

> %timeit sum(int(digit) for digit in str(n))
100000 loops, best of 3: 2.04 us per loop

If you want to keep summing the digits until you get a single-digit number (one of my favorite characteristics of numbers divisible by 9) you can do:如果你想继续对数字求和,直到得到一个位数(我最喜欢的数字可以被 9 整除的特征之一),你可以这样做:

def digital_root(n):
    x = sum(int(digit) for digit in str(n))
    if x < 10:
        return x
    else:
        return digital_root(x)

Which actually turns out to be pretty fast itself...事实证明,这本身就相当快......

%timeit digital_root(12312658419614961365)

10000 loops, best of 3: 22.6 µs per loop

This might help这可能会有所帮助

def digit_sum(n):
    num_str = str(n)
    sum = 0
    for i in range(0, len(num_str)):
        sum += int(num_str[i])
    return sum

Found this on one of the problem solving challenge websites.在解决问题的挑战网站之一上找到了这个。 Not mine, but it works.不是我的,但它有效。

num = 0            # replace 0 with whatever number you want to sum up
print(sum([int(k) for k in str(num)]))

Doing some Codecademy challenges I resolved this like:做一些 Codecademy 挑战我解决了这个问题:

def digit_sum(n):
    digits = []
    nstr = str(n)
    for x in nstr:
        digits.append(int(x))
    return sum(digits)

Edit: ANSWER IS NOT FOR THE QUESTION.编辑:答案不适合这个问题。
Question is to add all the digits of the number and return it.问题是将数字的所有数字相加并返回。

What I answered is to add all the digits of the numbers until single-digit number is reached.我的回答是将数字的所有数字相加,直到达到一位数。

EDIT END The best way is to use math.编辑结束最好的方法是使用数学。
I knew this from school.(kinda also from codewars)我从学校知道这一点。(有点也来自代码战)

def digital_sum(num):
    return (num % 9) or num and 9

Just don't know how this works in code, but I know it's maths只是不知道这在代码中是如何工作的,但我知道这是数学

If a number is divisible by 9 then, it's digital_sum will be 9,如果一个数可以被 9 整除,那么它的 digital_sum 将是 9,
if that's not the case then num % 9 will be the digital sum.如果不是这种情况,那么num % 9将是数字总和。

You can also use this: 您还可以使用以下命令:

def sum_digits(num):
    num = str(num)
    digitSum = 0
    for i in num:
        digitSum += int(i)
    return digitSum
print sum_digits(875)

尝试这个

    print(sum(list(map(int,input("Enter your number ")))))
def digitsum(n):
    result = 0
    for i in range(len(str(n))):
        result = result + int(str(n)[i:i+1])
    return(result)

"result" is initialized with 0. “结果”初始化为 0。

Inside the for loop, the number(n) is converted into a string to be split with loop index(i) and get each digit.在 for 循环中,number(n) 被转换成一个字符串,用循环 index(i) 分割并得到每个数字。 ---> str (n)[ i:i+1 ] ---> str (n)[ i:i+1 ]

This sliced digit is converted back to an integer ----> int (str(n)[i:i+1])这个切片后的数字被转换回整数----> int (str(n)[i:i+1])

And hence added to result.因此添加到结果中。

def sumOfDigits():

    n=int(input("enter digit:")) 
    sum=0
    while n!=0 :

        m=n%10
        n=n/10
        sum=int(sum+m)

    print(sum)

sumOfDigits()
reduce(op.add,map(int,list(str(number))))

Test:测试:

from datetime import datetime
number=49263985629356279356927356923569976549123548126856926293658923658923658923658972365297865987236523786598236592386592386589236592365293865923876592385623987659238756239875692387659238756239875692856239856238563286598237592875498259826592356923659283756982375692835692385653418923564912354687123548712354827354827354823548723548235482735482354827354823548235482354823548235482735482735482735482354823548235489235648293548235492185348235481235482354823548235482354823548235482354823548234



startTime = datetime.now()

for _ in  range(0,100000) :
    out=reduce(op.add,map(int,list(str(number))))

now=datetime.now()
runningTime=(now - startTime)

print ("Running time:%s" % runningTime)
print(out)

Running time:0:00:13.122560 2462运行时间:0:00:13.122560 2462

I cam up with a recursive solution:我想出了一个递归解决方案:

def sumDigits(num):
#   print "evaluating:", num
  if num < 10:
    return num

  # solution 1
#   res = num/10
#   rem = num%10
#   print "res:", res, "rem:", rem
#   return sumDigits(res+rem)

    # solution 2
  arr = [int(i) for i in str(num)]
  return sumDigits(sum(arr))

# print(sumDigits(1))
# print(sumDigits(49))
print(sumDigits(439230))
# print(sumDigits(439237))

Here is a solution without any loop or recursion but works for non-negative integers only (Python3):这是一个没有任何循环或递归但仅适用于非负整数的解决方案(Python3):

def sum_digits(n):
    if n > 0:
        s = (n-1) // 9    
        return n-9*s
    return 0

A base 10 number can be expressed as a series of the form一个以 10 为底的数可以表示为一系列形式

a × 10^ p + b × 10^ p-1 .. z × 10^ 0 a × 10^ p + b × 10^ p-1 .. z × 10^ 0

so the sum of a number's digits is the sum of the coefficients of the terms.所以数字的数字之和是各项系数的和。

Based on this information, the sum of the digits can be computed like this:基于此信息,可以像这样计算数字的总和:

import math

def add_digits(n):
    # Assume n >= 0, else we should take abs(n)
    if 0 <= n < 10:
        return n
    r = 0
    ndigits = int(math.log10(n))
    for p in range(ndigits, -1, -1):
        d, n = divmod(n, 10 ** p)
        r += d
    return r

This is effectively the reverse of the continuous division by 10 in the accepted answer.这实际上是接受答案中连续除以 10 的逆过程。 Given the extra computation in this function compared to the accepted answer, it's not surprising to find that this approach performs poorly in comparison: it's about 3.5 times slower, and about twice as slow as鉴于与接受的答案相比,此函数中的额外计算,发现这种方法相比之下表现不佳也就不足为奇了:它慢了大约 3.5 倍,大约慢了两倍

sum(int(x) for x in str(n))

This is how i do it myself, which can properly handle arbitrary precision integers without any BigInt library :这就是我自己做的,它可以在没有任何 BigInt 库的情况下正确处理任意精度整数:

function sumdigits(x,k,z){

    gsub(/[^1-9]+/,"",x)    # throw away junk, and all 0's
    z += gsub(++k, "",x)    # get rid of all the 1's

    while ( x!="" ) {  

       # process 2 numbers at a time, so 
       # even in worst case, the while() loop
       # is only called 4 cycles, while offering 
       # rapid early-exit.
 
       z +=  (++k * gsub(k,"",x))+\
             (++k * gsub(k,"",x)) ;
    }
    return z 
}

for the fun of it, i randomly generated 3 synthetically large integers, each with 46,539,361 decimal digits, with sums of digits well over 200-million each为了好玩,我随机生成了 3 个合成大整数,每个整数有46,539,361十进制数字,每个数字的总和超过 2 亿

214,942,897 217,165,213 223,275,043 214,942,897 217,165,213 223,275,043

on my 2018 system, it averaged about 1.75 secs or so.在我 2018 年的系统上,它平均大约 1.75 秒左右。

For a smaller inputs :对于较小的输入:

0.807 secs for 23,019,933-digit long integer summing up to 102,221,680 0.109 secs for 2,829,207-digit long integer summing up to 13,258,766 0.807秒的23,019,933-digit长整型总结到102,221,680 0.109秒为2,829,207-digit长整型总结到13,258,766

def digits_sum(a):
    sum = 0
    for i in range(len(str(a))):
        sum += a // 10 ** i % 10
    return sum

Whether it's faster to work with math or strings here depends on the size of the input number.在这里使用数学或字符串是否更快取决于输入数字的大小。

For small numbers, use math (division and modulus):对于小数,使用数学(除法和模数):

def sum_digits_math(n):
    r = 0
    while n:
        r, n = r + n % 10, n // 10
    return r

For large numbers, use the string domain:对于大数,使用字符串域:

def sum_digits_str_dumb(n):
    """from OP https://stackoverflow.com/q/14939953/674039"""
    return sum(int(i) for i in str(n))

def sum_digits_str_fast(n):
    d = str(n)
    return sum(int(s) * d.count(s) for s in "123456789")

The crossover point, where using division and modulus begins to lose out against working in the string domain, is at numbers approximately 27 digits long (where the blue line crosses the red line in the chart below):使用除法和模数开始失去在字符串域中工作的交叉点位于大约 27 位长的数字处(蓝线与下图中的红线相交):

简介1

The performance profile for using math just gets worse as the input number is bigger, but the string domain appears to scale linearly in the length of the input.随着输入数字越大,使用数学的性能配置文件越差,但字符串域似乎在输入长度上线性缩放。 The code that was used to generate these graphs is here , I'm using CPython 3.10.2 on macOS.用于生成这些图表的代码 在这里,我在 macOS 上使用 CPython 3.10.2。

Why is the highest rated answer 3.70x slower than this ?为什么评分最高的答案比这慢3.70 倍

% echo; ( time (nice echo 33785139853861968123689586196851968365819658395186596815968159826259681256852169852986 \
 | mawk2 'gsub(//,($_)($_)($_))+gsub(//,($_))+1' | pvE0 \
 | mawk2 '
   
   function __(_,___,____,_____) {

                  ____=gsub("[^1-9]+","",_)~""
                ___=10
       while((+____<--___) && _) {
            _____+=___*gsub(___,"",_) 
       }
       return _____+length(_) } 

    BEGIN { FS=OFS=ORS
                RS="^$" 
    } END { 
            print __($!_) }' )| pvE9 ) | gcat -n | lgp3 ;

      in0:  173MiB 0:00:00 [1.69GiB/s] [1.69GiB/s] [<=>                                            ]
     out9: 11.0 B 0:00:09 [1.15 B/s] [1.15 B/s] [<=>                                               ]
      in0:  484MiB 0:00:00 [2.29GiB/s] [2.29GiB/s] [  <=>                                          ]
( nice echo  | mawk2 'gsub(//,($_)($_)($_))+gsub(//,($_))+1' | pvE 0.1 in0 | )  

 8.52s user 1.10s system 100% cpu 9.576 total
 1  2822068024



% echo; ( time ( nice echo 33785139853861968123689586196851968365819658395186596815968159826259681256852169852986 \
     \
     | mawk2 'gsub(//,($_)($_)($_))+gsub(//,($_))+1' | pvE0 \
     |  gtr -d '\n' \
     \
     |  python3 -c 'import math, os, sys;

        [ print(sum(int(digit) for digit in str(ln)), \
                                            end="\n") \
         \
         for ln in sys.stdin ]' )| pvE9 ) | gcat -n | lgp3 ;


      in0:  484MiB 0:00:00 [ 958MiB/s] [ 958MiB/s] [     <=>                                       ]
     out9: 11.0 B 0:00:35 [ 317miB/s] [ 317miB/s] [<=>                                             ]
( nice echo  | mawk2 'gsub(//,($_)($_)($_))+gsub(//,($_))+1' | pvE 0.1 in0 | )  

 35.22s user 0.62s system 101% cpu 35.447 total
     1  2822068024

And that's being a bit generous already.这已经有点大方了。 On this large synthetically created test case of 2.82 GB, it's 19.2x slower .在这个 2.82 GB 的大型综合测试用例中,它了 19.2 倍。

 % echo; ( time ( pvE0 < testcases_more108.txt  |  mawk2 'function __(_,___,____,_____) { ____=gsub("[^1-9]+","",_)~"";___=10; while((+____<--___) && _) { _____+=___*gsub(___,"",_) }; return _____+length(_) } BEGIN { FS=RS="^$"; CONVFMT=OFMT="%.20g" } END { print __($_) }'  ) | pvE9 ) |gcat -n | ggXy3  | lgp3; 

      in0:  284MiB 0:00:00 [2.77GiB/s] [2.77GiB/s] [=>                             ]  9% ETA 0:00:00
     out9: 11.0 B 0:00:11 [1016miB/s] [1016miB/s] [<=>                                             ]
      in0: 2.82GiB 0:00:00 [2.93GiB/s] [2.93GiB/s] [=============================>] 100%            
( pvE 0.1 in0 < testcases_more108.txt | mawk2 ; )

  8.75s user 2.36s system 100% cpu 11.100 total
     1  3031397722

% echo; ( time ( pvE0 < testcases_more108.txt  | gtr -d '\n' |  python3 -c 'import sys; [ print(sum(int(_) for _ in str(__))) for __ in sys.stdin ]' ) | pvE9 ) |gcat -n | ggXy3  | lgp3;  


      in0: 2.82GiB 0:00:02 [1.03GiB/s] [1.03GiB/s] [=============================>] 100%            
     out9: 11.0 B 0:03:32 [53.0miB/s] [53.0miB/s] [<=>                                             ]
( pvE 0.1 in0 < testcases_more108.txt | gtr -d '\n' | python3 -c ; )  

  211.47s user 3.02s system 100% cpu 3:32.69 total
     1  3031397722

————————————————————— —————————————————————

UPDATE : native python3 code of that concept - even with my horrific python skills, i'm seeing a 4x speedup :更新:该概念的本机 python3 代码——即使我有可怕的 python 技能,我也看到了 4 倍的加速:

% echo; ( time ( pvE0 < testcases_more108.txt  \
\
 |python3 -c 'import re, sys;

  print(sum([ sum(int(_)*re.subn(_,"",__)[1] 

     for _ in [r"1",r"2", r"3",r"4",
               r"5",r"6",r"7",r"8",r"9"])

 for __ in sys.stdin ]))' |pvE9))|gcat -n| ggXy3|lgp3   

      in0: 1.88MiB 0:00:00 [18.4MiB/s] [18.4MiB/s] [>                              ]  0% ETA 0:00:00
     out9: 0.00 B 0:00:51 [0.00 B/s] [0.00 B/s] [<=>                                               ]
      in0: 2.82GiB 0:00:51 [56.6MiB/s] [56.6MiB/s] [=============================>] 100%            
     out9: 11.0 B 0:00:51 [ 219miB/s] [ 219miB/s] [<=>                                             ]

( pvE 0.1 in0 < testcases_more108.txt | python3 -c  | pvE 0.1 out9; ) 



48.07s user 3.57s system 100% cpu 51.278 total
 1  3031397722

Even the smaller test case managed a 1.42x speed up :即使是较小的测试用例也能实现 1.42 倍的加速:

 echo; ( time (nice echo 33785139853861968123689586196851968365819658395186596815968159826259681256852169852986 \ 
 | mawk2 'gsub(//,($_)($_)$_)+gsub(//,$_)+1' ORS='' | pvE0 | python3 -c 'import re, sys; print(sum([ sum(int(_)*re.subn(_,"",__)[1] for _ in [r"1",r"2", r"3",r"4",r"5",r"6",r"7",r"8",r"9"]) for __ in sys.stdin ]))'  | pvE9  ))  |gcat -n | ggXy3 | lgp3 


      in0:  484MiB 0:00:00 [2.02GiB/s] [2.02GiB/s] [  <=>                                          ]
     out9: 11.0 B 0:00:24 [ 451miB/s] [ 451miB/s] [<=>                                             ]
( nice echo  | mawk2 'gsub(//,($_)($_)$_)+gsub(//,$_)+1' ORS='' | pvE 0.1 in0)

 20.04s user 5.10s system 100% cpu 24.988 total
   1    2822068024
num = 123
dig = 0
sum = 0
while(num > 0):
  dig = int(num%10)
  sum = sum+dig
  num = num/10

print(sum) // make sure to add space above this line print(sum) // 确保在此行上方添加空格

You can try this你可以试试这个

def sumDigits(number):
    sum = 0
    while(number>0):
        lastdigit = number%10
        sum += lastdigit
        number = number//10

    return sum

you can also try this with built_in_function called divmod() ;您也可以使用名为 divmod() 的 built_in_function 尝试此操作;

number = int(input('enter any integer: = '))
sum = 0
while number!=0: 
    take = divmod(number, 10) 
    dig = take[1] 
    sum += dig 
    number = take[0] 
print(sum) 

you can take any number of digit你可以取任意位数

Here is the best solution I found:这是我找到的最佳解决方案:

function digitsum(n) {
    n = n.toString();
    let result = 0;
    for (let i = 0; i < n.length; i++) {
        result += parseInt(n[i]);
    }
    return result;
}
console.log(digitsum(192));

It only works for three-digit numbers, but it works它只适用于三位数,但它有效

a = int(input())
print(a // 100 + a // 10 % 10 + a % 10)
n = str(input("Enter the number\n"))

list1 = []

for each_number in n:

        list1.append(int(each_number))

print(sum(list1))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM