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.
-
sorry, when I wrote the question the formatting wasn't messed up like thatuser170800– user17080003/10/2015 18:27:15Commented Mar 10, 2015 at 18:27
-
What type are you storing the number in?user40980– user4098003/10/2015 18:27:26Commented Mar 10, 2015 at 18:27
-
I am storing the number as a floatuser170800– user17080003/10/2015 18:28:39Commented Mar 10, 2015 at 18:28
-
3Just output the number to a string and go through it char by char.whatsisname– whatsisname03/10/2015 19:37:15Commented Mar 10, 2015 at 19:37
-
1@user170800 you may wish to delve into the floating-point tag and see other similar questions. I've got an answer elsewhere that my help you: When do rounding problems become a real problem? Is the least significant digit being one off really a big deal? (and can work on explaining what is going on at the bit level later).user40980– user4098003/10/2015 20:01:33Commented Mar 10, 2015 at 20:01
1 Answer 1
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:
- 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
- Python list comprehensions combined with standard functions are extremely useful for anything that involves "do something with this list of something".
- When using floating point math, you should never expect exact results except in trivial cases (like 0.0) because of precision issues.
-
I'd use the exact same approach in C++, though the code would be a lot longer.user53141– user5314103/10/2015 20:09:54Commented Mar 10, 2015 at 20:09