There is such a function:

def sumDigits(number): return sum([int(i) for i in str(a)]) 

For positive numbers, it returns correct values, but not true values ​​for negative ones. Example: calling the function for the number -35 should return 2, but does not work, because str(a) considers the minus sign as a separate character.

How to solve this problem?

  • The title says "sum of digits", in the example that you gave sumDigits(-35) should be equal to 2. What is the task you are facing, that with the sum of digits of a negative number the first digit is subtracted from the sum of the others? How do you expect the result, for example, from the source numbers -911 , -10000 ? - tutankhamun
  • -9 +1 +1 = -7 -1 +0 + 0 + 0 = -1 - gudfar
  • And about the applicability of this task can you say something? Why is this unusual amount calculated? - tutankhamun
  • This is all codewars.com. I first solved the problem in another way, then googled this one, but with an error. I'm new to python, I think going from php to python - gudfar
  • But if my version worked on codewars.com tests, it means that the minus should not affect the first digit (in the sense of it, too, must be added) - tutankhamun

6 answers 6

You can, for example, consider the sum of the digits of the absolute value

 def sumDigits(number): return sum([int(i) for i in str(abs(number))]) 
  • thanks It works ! - gudfar
  • @gudfar: the code in this answer returns 8 for -35 , not 2 as the question is indicated. Other answers try to take into account the presence of the mark in the number. - jfs
  • one
    aside: brackets [] are not needed here: sum(int(digit) for digit in str(abs(number))) or sum(map(int, str(abs(number)))) - jfs

Can you check whether each character in the string can be interpreted as a number

 def sumDigits(number): return sum([int(i) for i in str(number) if i.isdigit()]) 

You can even pass a number to such a function, the result will be the sum of all digits in the string

 >>> sumDigits('-123 строка') 6 

Updated

If you still need to take into account the minus sign when adding, then this is an option on regular expressions

 def sumDigits(number): return sum([int(x) for x in re.findall('(?:-)?\d', str(number))]) >>> sumDigits('-123') 4 
  • According to the logic of the author, 4 should work out. -1 + 2 + 3 - slippyk am
  • abs needs to be added and then everything is OK) - gudfar
  • @slippyk something does not agree then, in the accepted answer also 6 comes out. andy.37 comes out right in his answer - FeroxTL
 def dig_sum(x): sx = str(x) if sx[0] == '+': return dig_sum(sx[1:]) elif sx[0] == '-': return dig_sum(sx[1:]) - 2 * int(sx[1]) else: return sum([int(i) for i in sx]) print dig_sum(35) --> 8 print dig_sum('+35') --> 8 print dig_sum(-35) --> 2 

    This sum of digits can be considered as the sum of digits without shamanism with the translation into a string and back:

     from __future__ import division import timeit def sum_digits(number): summ = 0 ab_numb = abs(number) divm = divmod while ab_numb > 10: ab_numb, remainder = divm(ab_numb, 10) summ += remainder if number > 0: return summ + ab_numb else: return summ - ab_numb 

    Now compare all the solutions:

     def sumDigits(number): return sum([int(i) for i in str(abs(number))]) def sumDigits_eval(number): return eval('+'.join([i for i in str(number)])) def sumDigits_regex(number): return sum([int(x) for x in re.findall('(?:-)?\d', str(number))]) print("Math: ", timeit.repeat("sum_digits(-34543)", "from __main__ import sum_digits", number=100000)) print("Str: ", timeit.repeat("sumDigits(-34543)", "from __main__ import sumDigits", number=100000)) print("Eval: ", timeit.repeat("sumDigits_eval(-34543)", "from __main__ import sumDigits_eval", number=100000)) print("Regexp: ", timeit.repeat("sumDigits_regex(-34543)", "from __main__ import sumDigits_regex", number=100000)) >>> Math: [0.24735833889623768, 0.24581550535393623, 0.24613614212789509] >>> Str: [0.407044484349559, 0.4065382805822204, 0.4061474403660761] >>> Eval: [2.771394191096233, 2.761938895909233, 2.76689131768166] >>> Regexp: [0.8407116740523968, 0.837011418938836, 0.835758841733524] print("Math: ", timeit.repeat("sum_digits(-310104588999943)", "from __main__ import sum_digits", number=100000)) print("Str: ", timeit.repeat("sumDigits(-310104588999943)", "from __main__ import sumDigits", number=100000)) >>> Math: [0.7094168680396982, 0.7092928830131481, 0.7118370393360973] >>> Str: [0.9090130545558752, 0.9149762416771967, 0.9091776836805323] 

      Here is another way for you:

       def sumDigits(number): return eval('+'.join([i for i in str(number)])) 

      PS The decision from the answer that you have marked as correct does not work.

      • it works, I ran the tests - gudfar
      • So you have a condition does not match the tests. Try it, it gives 8 to -35, but the condition should be 2. - Ruslan Terekhov
      • I also do not have enough rating to comment not under my posts, so here I will write. In the solution m9_psy ( ru.stackoverflow.com/a/542660/214570 ) you need to replace '> 10' with '> = 10', otherwise it works incorrectly for 1000. - Ruslan Terekhov
       def sumDigits(number): if number >= 0: return sum([int(i) for i in str(number)]) else: number = abs(number) summa = sum([int(i) for i in str(number)]) summa -= int(str(number)[0]) * 2 return summa 

      It seems to work =)