简体   繁体   中英

Sum the digits of a number

If I want to find the sum of the digits of a number, ie:

  • Input: 932
  • Output: 14 , which is (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 :

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:

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:

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,
if that's not the case then num % 9 will be the digital sum.

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.

Inside the for loop, the number(n) is converted into a string to be split with loop index(i) and get each digit. ---> str (n)[ i:i+1 ]

This sliced digit is converted back to an integer ----> 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

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):

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

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. 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

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 :

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

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

on my 2018 system, it averaged about 1.75 secs or so.

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

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):

简介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.

Why is the highest rated answer 3.70x slower than this ?

% 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 .

 % 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 :

% 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 :

 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

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() ;

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))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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