Reputation: 43
What I need to do is use integer arithmetic to convert fractions into floating point numbers. The number of decimal places needed is specified as a variable DECIMALS
. Each fraction is contained in a tuple of integers, for example (1, 3)
. The first item is the numerator and the second is the denominator. The tuples are contained in a list called fractions
.
This is my code so far:
fractions = [(1,7), (2,3), (22,7), (7001,7), (9,3), (611951,611953), (1,11), (1,7689585)]
DECIMALS = 10**40 # 40 decimal places
for fraction in fractions:
x = DECIMALS*fraction[0]/fraction[1]
print x
When i run the code this is what i get:
1428571428571428571428571428571428571428
6666666666666666666666666666666666666666
31428571428571428571428571428571428571428
10001428571428571428571428571428571428571428
30000000000000000000000000000000000000000
9999967317751526669531810449495304377950
909090909090909090909090909090909090909
1300460297922449651053990559958697
The problem is that I need to format this into the correct decimal format. What I tried was
print "0.%.40d" % (x)
But of course this will only help me with the first 2 decimals; the rest will be wrong. I thought about dividing it up so I can calculate the fractions indivdually to make them easier to format, but I have no idea how to do this. The catch is that all the fractions need to be processed by the same code. I also want it to be rounded properly but thats not a big deal right now.
Upvotes: 1
Views: 1216
Reputation:
If it strictly formatting, as implied by your question, you could, of course, do this with integers and strings alone:
def intF(n, d, l=40):
s=str(n*10**l / d)
if len(s) < l:
return '0.{:0>{width}}'.format(s,width=l)
if len(s) > l:
return s[0:len(s)-l]+'.'+s[len(s)-l:]
return '0.'+s
for f in [(1,7), (2,3), (22,7), (7001,7), (9,3),
(611951,611953), (1,11),(1,7689585)]:
print intF(*f)
print float(f[0]) / f[1]
print
Output:
0.1428571428571428571428571428571428571428
0.142857142857
0.6666666666666666666666666666666666666666
0.666666666667
3.1428571428571428571428571428571428571428
3.14285714286
1000.1428571428571428571428571428571428571428
1000.14285714
3.0000000000000000000000000000000000000000
3.0
0.9999967317751526669531810449495304377950
0.999996731775
0.0909090909090909090909090909090909090909
0.0909090909091
0.0000001300460297922449651053990559958697
1.30046029792e-07
The last digit will not correctly round and it will not handle edge cases ('inf', 'NaN', division by zero, etc) correctly.
Works in a pinch I suppose.
Why not use the batteries included though, like Decimal or Fraction?
Upvotes: 0
Reputation: 35552
You mean something like this:
from fractions import Fraction
import decimal
decimal.getcontext().prec = 50
fractions = [(1,7), (2,3), (22,7), (7001,7), (9,3), (611951,611953), (1,11),(1,7689585)]
su=Fraction(0)
for i, t in enumerate(fractions,1):
f=Fraction(*t)
su+=Fraction(*t)
d=decimal.Decimal(f.numerator) / decimal.Decimal(f.denominator)
print '{} becomes {}'.format(t,f)
print '\tfloat of that is: {}'.format(float(f))
print '\tDecimal: {}'.format(d)
print '\t{} elements cum sum of the list: {}\n'.format(i,su)
Prints:
(1, 7) becomes 1/7
float of that is: 0.142857142857
Decimal: 0.14285714285714285714285714285714285714285714285714
1 elements cum sum of the list: 1/7
(2, 3) becomes 2/3
float of that is: 0.666666666667
Decimal: 0.66666666666666666666666666666666666666666666666667
2 elements cum sum of the list: 17/21
(22, 7) becomes 22/7
float of that is: 3.14285714286
Decimal: 3.1428571428571428571428571428571428571428571428571
3 elements cum sum of the list: 83/21
(7001, 7) becomes 7001/7
float of that is: 1000.14285714
Decimal: 1000.1428571428571428571428571428571428571428571429
4 elements cum sum of the list: 21086/21
(9, 3) becomes 3
float of that is: 3.0
Decimal: 3
5 elements cum sum of the list: 21149/21
(611951, 611953) becomes 611951/611953
float of that is: 0.999996731775
Decimal: 0.99999673177515266695318104494953043779505942449829
6 elements cum sum of the list: 12955044968/12851013
(1, 11) becomes 1/11
float of that is: 0.0909090909091
Decimal: 0.090909090909090909090909090909090909090909090909091
7 elements cum sum of the list: 142518345661/141361143
(1, 7689585) becomes 1/7689585
float of that is: 1.30046029792e-07
Decimal: 1.3004602979224496510539905599586973809379829990825E-7
8 elements cum sum of the list: 121767437017889092/120778724977295
The fraction module allows you to work with rational numbers (without converting to a float). Once you have put them into a Fraction class, you can do arithmetic with them (just like in grade school)
Like this:
>>> Fraction(1,3) + Fraction(3,4)
Fraction(13, 12)
>>> Fraction(1,3) + Fraction(1,6)
Fraction(1, 2)
>>> Fraction(1,2).numerator
1
>>> Fraction(1,2).denominator
2
The Fraction module is part of default Python distribution (since 2.6).
To convert that to a float, do float(Fraction(17,18))
for example or use Fraction.numerator
and Fraction().denominator
in a Decimal class variable for arbitrary precision conversion.
Like so:
>>> decimal.Decimal(su.numerator) / decimal.Decimal(su.denominator)
Decimal('1008.186144047968368606384293')
or:
>>> float(su.numerator) / su.denominator
1008.1861440479684
Upvotes: 2
Reputation: 799150
Avoid floating point numbers in the first place.
>>> decimal.getcontext().prec = 50
>>> [str((decimal.Decimal(x) / decimal.Decimal(y)).quantize(decimal.Decimal(10) ** -40)) for (x, y) in FRACTIONS]
['0.1428571428571428571428571428571428571429', '0.6666666666666666666666666666666666666667', '3.1428571428571428571428571428571428571429', '1000.1428571428571428571428571428571428571429', '3.0000000000000000000000000000000000000000', '0.9999967317751526669531810449495304377951', '0.0909090909090909090909090909090909090909', '1.300460297922449651053990559958697E-7']
Upvotes: 1