2

I am trying to find the sum of 2000 decimal digits of a number created by a fraction, a/b. I am getting a lot of the digits until i hit NaN (not a number). I hit NaN when the loop runs around 310 times. How do I get the rest of the digits?

Here is the code I'm using:

import math
a = 3.00
b = 857.00
c = a/b
result = 0.0
s = 0.0
for x in range(0, 2000 , 1):
    s= c % 10
    result += int(s)
    c *= 10

print result
Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
spørreren
  • 75
  • 3
  • 1
    Two remarks: `import math` is not needed, as you don't use any functions from the `math` module. And `range(0, 2000, 1)` can be simplified to `range(2000)`. – mkrieger1 Mar 26 '15 at 13:31
  • Any particluar reason why you can't use the [`Decimal` module](https://docs.python.org/2/library/decimal.html)? – Anshul Goyal Mar 26 '15 at 13:34
  • becouse i have an assignment where decimal module is not allowed – spørreren Mar 26 '15 at 13:35
  • c is going to infinity which results in s becoming a NaN because you are effectively multiplying aba/b by 10^310. You are trying to deal with 2000 digit decimals and that can't be done using a native data type – kdopen Mar 26 '15 at 13:37
  • ahhh, how do i remove the integers then? – spørreren Mar 26 '15 at 13:39
  • Another remark: Don't initialize `s` as a floating point number (`0.0`). Use an integer (`0`) instead, it has unlimited size in Python and you are accumulating integers only anyway. – mkrieger1 Mar 26 '15 at 13:39
  • 1
    Your problem statement is unclear. Are you trying to sum the *digits* of a/b? – kdopen Mar 26 '15 at 13:39
  • im trying to sum all the decimals of a number that is produced by a/b. if the number was 0.2847 i would sum (2+8+4+7) – spørreren Mar 26 '15 at 13:43
  • is there any other way to sum the decimals, than how my code do it? – spørreren Mar 26 '15 at 13:47
  • You will run into many problems with floating point and rounding in this approach because the `c *= 10` will keep bringing in extra digits. – kdopen Mar 26 '15 at 13:50

1 Answers1

2

You are using the wrong approach. Using a direct float division limits your ability to calculate the decimals, because integers can be converted to floats based on the underlying libraries, as mentioned in documentation, and by default float would not save numbers to arbitrary precision (2000 in your case):

When passing in a string, values for NaN and Infinity may be returned, depending on the underlying C library. Float accepts the strings nan, inf and -inf for NaN and positive or negative infinity. The case and a leading + are ignored as well as a leading - is ignored for NaN. Float always represents NaN and infinity as nan, inf or -inf.

In your case (as also in mine), that limit happens to be 2**1024. Go to your python prompt, and try running the following:

>>> float(2**1024)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to float
>>> float(2**1023)
8.98846567431158e+307

The above number basically corresponds to the value that c would have had in your code above, in the end of the 310th iteration, and given that c is defined as float, it would throw the error.

Basically, this means that any float number equal to or bigger than 2 **1024 will be converted to nan or inf, and hence your existing code won't run.

Also, note that floating point calculations have limitations anyway, so your answer would not have been correct for such high precision.

So instead, I suggest you calculate the remainder in each turn on dividing by the denominator, b, as used in the following:

a = 3
b = 857
result = 0
if a:
    for x in range(0, 2000 , 1):
        a = a*10
        result += a / b
        a = a%b    

>>> print result
9056
Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
  • This hits exactly what I was suggesting above because the floating point representation keeps bringing in spurious digits – kdopen Mar 26 '15 at 13:52
  • @kdopen When I initially read the question, for a few moments, I wasn't able to figure out why the nan's would appear given that python supports arbitarily large ints. Then I read the docs, and realized this was a limitation with the floats :) – Anshul Goyal Mar 26 '15 at 13:54
  • Yep, but the 'correct' anser for his values of a and b is `43`. Yours got `9056`, my floating approach got `189`. That's why I said to go with a string approach – kdopen Mar 26 '15 at 13:58
  • 1
    @kdopen Are you serious? He is looking for sum of 2000 digits after the decimal, and the sum is ***only*** 189? FWIW, your solution goes upto some 10 or 20 digits after the decimal. Using floating point in any way is simply not the answer. – Anshul Goyal Mar 26 '15 at 14:00
  • thanks man this worked perfectly! i guess i was on the right track but i dont yet totally understand why i got NaN in for my previus code – spørreren Mar 26 '15 at 14:00
  • I suggest using `a // b` in place of `a / b`, to make it clear that it's a floor division (and so that the code works under Python 3). – Mark Dickinson Apr 24 '15 at 16:45