繁体   English   中英

对一个数的数字求和

[英]Sum the digits of a number

如果我想找到一个数字的数字总和,即:

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

最快的方法是什么?

我本能地做了:

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

我在网上找到了这个:

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

哪种方法最适合提高速度,还有其他更快的方法吗?

你发布的两行都很好,但你可以纯粹用整数来做,这将是最有效的:

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

或使用divmod

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

稍微快一点的是使用单个赋值语句:

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

如果你想继续对数字求和,直到得到一个位数(我最喜欢的数字可以被 9 整除的特征之一),你可以这样做:

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

事实证明,这本身就相当快......

%timeit digital_root(12312658419614961365)

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

这可能会有所帮助

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

在解决问题的挑战网站之一上找到了这个。 不是我的,但它有效。

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

做一些 Codecademy 挑战我解决了这个问题:

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

编辑:答案不适合这个问题。
问题是将数字的所有数字相加并返回。

我的回答是将数字的所有数字相加,直到达到一位数。

编辑结束最好的方法是使用数学。
我从学校知道这一点。(有点也来自代码战)

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

只是不知道这在代码中是如何工作的,但我知道这是数学

如果一个数可以被 9 整除,那么它的 digital_sum 将是 9,
如果不是这种情况,那么num % 9将是数字总和。

您还可以使用以下命令:

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)

“结果”初始化为 0。

在 for 循环中,number(n) 被转换成一个字符串,用循环 index(i) 分割并得到每个数字。 ---> str (n)[ i:i+1 ]

这个切片后的数字被转换回整数----> int (str(n)[i:i+1])

因此添加到结果中。

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

测试:

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)

运行时间:0:00:13.122560 2462

我想出了一个递归解决方案:

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

这是一个没有任何循环或递归但仅适用于非负整数的解决方案(Python3):

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

一个以 10 为底的数可以表示为一系列形式

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

所以数字的数字之和是各项系数的和。

基于此信息,可以像这样计算数字的总和:

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

这实际上是接受答案中连续除以 10 的逆过程。 鉴于与接受的答案相比,此函数中的额外计算,发现这种方法相比之下表现不佳也就不足为奇了:它慢了大约 3.5 倍,大约慢了两倍

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

这就是我自己做的,它可以在没有任何 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 
}

为了好玩,我随机生成了 3 个合成大整数,每个整数有46,539,361十进制数字,每个数字的总和超过 2 亿

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

在我 2018 年的系统上,它平均大约 1.75 秒左右。

对于较小的输入:

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

在这里使用数学或字符串是否更快取决于输入数字的大小。

对于小数,使用数学(除法和模数):

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

对于大数,使用字符串域:

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

使用除法和模数开始失去在字符串域中工作的交叉点位于大约 27 位长的数字处(蓝线与下图中的红线相交):

简介1

随着输入数字越大,使用数学的性能配置文件越差,但字符串域似乎在输入长度上线性缩放。 用于生成这些图表的代码 在这里,我在 macOS 上使用 CPython 3.10.2。

为什么评分最高的答案比这慢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

这已经有点大方了。 在这个 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

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

更新:该概念的本机 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

即使是较小的测试用例也能实现 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) // 确保在此行上方添加空格

你可以试试这个

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

    return sum

您也可以使用名为 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) 

你可以取任意位数

这是我找到的最佳解决方案:

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

它只适用于三位数,但它有效

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