[Tutor] converting decimals to fractions
Tim Peters
tim.one@home.com
Mon, 8 Oct 2001 13:47:53 -0400
[Blake.Garretson@dana.com]
> This is less of a Python question than it is an algorithm question, but
> it should still apply since Python has some cool data structures
> available to apply to the solution.
In this case, I think some simple arithmetic will suffice.
> I have a script that does some length calculations and prints out results
> in decimal inches. (e.g. 1.537", 4.230", etc.) Converting these to
> fractions of an inch is simple enough (e.g. 1+537/1000, 4+23/100, etc.),
> but suppose I only want answers in the standard fractions of an inch
> (i.e. fourths of and inch, thirty-seconds of an inch, etc.).
The "etc" is important: how far down do you want to go? That is, is 1/32
the smallest granularity you care about?
BTW, in my college days, I applied for a job on the Harley-Davidson assembly
line. I barely made it: during the interview, the foreman looked me in the
eyes and demanded "how many sixty-fourths of an inch are in an inch?". It
seemed like *such* a stupid question, I asked him to repeat it. He did.
Then it seemed like it must be a trick question, and my mind raced futilely
looking for "the trick". After about a minute, he lost patience and asked
for my answer. Hesitant and defeated, I weakly asked "umm, 64?". "Right!"
he beamed, "Now let's see if you can read a micrometer.".
def tofrac(x, largest_denominator=32):
"""Return triple (i, j, k) where x ~= i + j/k.
x >= 0 is required.
i, j and k are integers >= 0, and k is > 0.
j and k have no factors in common, unless j is 0.
Optional argument largest_denominator (default 32) should be a
power of 2, and is the largest value k can have.
"""
if not x >= 0:
raise ValueError("x must be >= 0")
scaled = int(round(x * largest_denominator))
whole, leftover = divmod(scaled, largest_denominator)
if leftover:
while leftover % 2 == 0:
leftover >>= 1
largest_denominator >>= 1
return whole, leftover, largest_denominator
format = "%d %d/%d"
print format % tofrac(1.537)
print format % tofrac(4.230)
print format % tofrac(4.230, 128)
print format % tofrac(4.240)
print format % tofrac(8)
That prints
1 17/32
4 7/32
4 29/128
4 1/4
8 0/32
> I'm looking for suggestions on implementation. My approach is to use a
> lookup table, probably in dictionary form. The table will contain "bins"
> of fractions in increments of 1/32 with upper and lower limits for the
> decimal equivlent. The limits would be calculated by adding and
> subtracting 1/64 to the base number. For instance, a given decimal
> would be determined to be 3/32 if the decimal equivalent was between
> 0.09375+0.015625 and 0.09375-0.015625.
The code above gets the same effect, pretty much by answering the question
"How many 32nds of an inch are in an inch?" <wink>: multiply by 32, round
to an int, then take the quotient and remainder from dividing by 32.