Python – Adding the Digits of a Number

floating pointloopspython

I am trying to write a program that asks the user for a decimal number and then calculates the sum of its digits. for example if the number is 123.25 then the sum will be 1+2+3+2+5=13.

I decided to first turn the number to 0.12325 (any number will be formatted this way but I am using the example) and then move the decimal point to the right one place and isolate the digits one by one.

here is what I got (I tried it in python and c++ i get the same problem in both):

number = float(raw_input ("please enter a Decimal number: "))
total = 0

while number >= 1:
    number = number / 10 ## turning 123.25 to 0.12325

while number > 0:
    number = number * 10 ## making 0.12325 to 1.2325
    total = total + int(number)  ## storing the digit on the left of the decimal point
    number = number  - int (number) ## getting rid of the digit left to the decimal point

print total

The problem is that everything works fine until the last digit. When it comes to the point where it's 5.0 than the statement number = number – int(number) gives me 1 instead of zero. It is supposed to be 5.0 – 5 = 0 but it isn't.

This is what I get when i print the number at every stage:

please enter a Decimal number: 123.25
0.12325
0.2325
0.325
0.25
0.5    ##### Here is where the problem starts #####
0.999999999999
0.999999999993
0.999999999929
..... here it goes on for  a while. I spared you the rest .....

More accurately, I printed the number at every step in the loop:

please enter a Decimal number: 123.25

number at start of loop:  0.12325
number after 'number * 10' :  1.2325
number at the end of the loop:  0.2325

number at start of loop:  0.2325
number after 'number * 10' :  2.325
number at the end of the loop:  0.325

number at start of loop:  0.325
number after 'number * 10' :  3.25
number at the end of the loop:  0.25

number at start of loop:  0.25
number after 'number * 10' :  2.5
number at the end of the loop:  0.5

number at start of loop:  0.5
number after 'number * 10' :  5.0
number at the end of the loop:  0.999999999999

All of a sudden it stops being accurate.

Best Answer

This can be done with the following python one-liner:

>>> f = 123.25
>>> sum(int(ch) for ch in str(f) if ch.isdigit())
13
>>>

To break down how this works:

Convert to string as @whatsisname recommends to avoid floating point rounding issues

str(f)

Create a list containing each character

ch for ch in str(f)

Throw out everything that isn't a digit

ch for ch in str(f) if isdigit(ch)

Convert everything in the result to an int

int(ch) for ch in str(f) if isdigit(ch)

Sum everything

sum(int(ch) for ch in str(f) if isdigit(ch))

There are three key points here:

  1. Do not be afraid to convert numbers to strings. The performance hit of doing so is usually inconsequential on modern machines, and this makes manipulating digits much more natural
  2. Python list comprehensions combined with standard functions are extremely useful for anything that involves "do something with this list of something".
  3. When using floating point math, you should never expect exact results except in trivial cases (like 0.0) because of precision issues.
Related Topic