2

It's a simple problem really, but I have been searching all over and cannot find the answer. Let's assume that we have a list of fractions made using the fractions module in python:

from fractions import Fraction

A = [Fraction(1, 3), Fraction(4, 14), Fraction(8, 21)]

I want to put them all on one base denominator. The output would be a list of all of the numerators plus the common denominator:

"""
A[0] ==> 7/21
A[1] ==> 6/21
A[2] ==> 8/21

Notice that the denominator 21 is the lowest we can go. 
"""

B = [7, 6, 8, 21] # Desired output style

How would I go about doing this in pure python (only using built in libraries).

Al-Baraa El-Hag
  • 770
  • 6
  • 15
  • The same way you would do it without python! – JeffUK Dec 18 '20 at 10:22
  • 2
    Get the LCM of the denominators. Then the numerator of each fraction is scaled by that LCM divided by the denominator of that fraction. – Dan D. Dec 18 '20 at 10:44
  • @DanD. technically they don't ask for the fractions in *lowest* common denominator, so you can just multiply everything together and get everything in 441ths :) – JeffUK Dec 18 '20 at 10:54
  • For LCM, see https://stackoverflow.com/questions/60703559/find-the-lcm-for-up-to-5-numbers – zvone Dec 18 '20 at 11:01

2 Answers2

4

There might be more elegant solutions than this but this works:

  1. You identify the combinations of you denominators

    import itertools
    combinations = itertools.combinations([x.denominator for x in A],2)
    

This will be an iterator: Then you find the least common multiplier with this function: Credit goes to this answer:

import math

def lcm(a, b):
    return abs(a*b) // math.gcd(a, b)

Then you run it on your iterator:

from functools import reduce
x = 1
for item in combinations:
    res = reduce(lcm, (a for a in item))
    if res > x:
        x = res

This gives you 21 I think from here it is easy to divide this with the denominator and multiply your numerator with that

Hint for your desired output - this although does not contain x (21) yet:

[(a * x/a.denominator).numerator for a in A]
Anna Semjén
  • 787
  • 5
  • 14
  • 1
    It looks like the call to `itertools.combinations` is unnecessary, and makes the loop quadratic instead of linear for no reason. You could just run `reduce` with `lcm` directly: `x = reduce(lcm, (a.denominator for a in A))`. Then you can return `[a.numerator * x // a.denominator for a in A] + [x]`. – Stef Jan 20 '22 at 18:39
  • 1
    Also note that since python3.9 there is `math.lcm`. You can call it with `reduce`, or you can call it on more than 2 arguments directly: `from math import lcm; x = lcm(*(a.denominator for a in A))` – Stef Jan 20 '22 at 18:41
0
from fractions import Fraction
import numpy as np

def reduction_fraction(A):    
    deno = []
    # get all the denominators
    for fraction in A:
        deno.append(fraction.denominator)
    
    result = []
    # put all the fraction on the least common multiple of the denominators
    for fraction in A:
        result.append(fraction.numerator * np.lcm.reduce(deno) / fraction.denominator)

    # add the least common multiple of the denominators at the end
    result.append(np.lcm.reduce(deno))

    return result
Vinz
  • 36
  • 5