Как упростить дробь в Python?

все еще изучаю Python, поэтому любая помощь приветствуется. Я написал функцию для получения дроби, но чаще всего дробь можно упростить. Мой код еще не делает этого. Есть идеи, как упростить дробь без использования каких-либо функций import? код:

def add_frac(n1, d1, n2, d2):
    frac = (((n1 * d1) + (n2 * d2)), (d1 * d2))
    return frac

пример: add_frac(1, 2, 1, 4) дает (6, 8) вместо (3, 4)

Любая помощь приветствуется!


person David    schedule 20.11.2020    source источник


Ответы (5)


Довольно наивный подход для начала, вы можете добавить некоторые проверки, чтобы сделать его более эффективным.

def simplify_frac(n, d):
    i = 2
    while i < min(n, d) + 1:
        if n % i == 0 and d % i == 0:
            n = n // i
            d = d // i
        else:
            i += 1
    return n, d

# Some examples 
In [105]: simplify_frac(2, 4)
Out[105]: (1, 2)

In [106]: simplify_frac(16, 36)
Out[106]: (4, 9)

In [107]: simplify_frac(7, 3)
Out[107]: (7, 3)

In [108]: simplify_frac(10, 1)
Out[108]: (10, 1)

In [109]: simplify_frac(1, 10)
Out[109]: (1, 10)

In [110]: simplify_frac(102, 10)
Out[110]: (51, 5)

In [111]: simplify_frac(110, 10)
Out[111]: (11, 1)

Мы используем оператор по модулю % для проверки остатка от целочисленного деления на i, если оба n and d имеют остаток 0, мы знаем, что i делит их.

person JunkyByte    schedule 20.11.2020

В дополнение к приведенным выше ответам, если вы не можете импортировать какие-либо другие библиотеки, вот реализация Fractions.gcd для Python 2.7 (скопировано из https://stackoverflow.com/a/11175154/10155740)

>>> print inspect.getsource(gcd)
def gcd(a, b):
    """Calculate the Greatest Common Divisor of a and b.

    Unless b==0, the result will have the same sign as b (so that when
    b is divided by it, the result comes out positive).
    """
    while b:
        a, b = b, a%b
    return a

поэтому, если вы включите это в свой код, вы должны получить что-то вроде:

def gcd(a, b):
    while b:
        a, b = b, a%b
    return a

def add_frac(n1, d1, n2, d2):
    frac = (((n1 * d1) + (n2 * d2)), (d1 * d2))
    return tuple(i//gcd(*frac) for i in frac)

print(add_frac(1,2,1,4))
# OUTPUT: (3, 4)
person QuadU    schedule 20.11.2020

Вот решение с рекурсивной реализацией gcd ​​с использованием алгоритма Евклида; он также работает с отрицательными числами:

def mygcd(a, b) :
    return gcd_rec(abs(a), abs(b))

def gcd_rec(a,b) :
    if a*b == 0 : return a+b
    if a <= b : return gcd_rec(a, b % a)
    return gcd_rec(a % b, b)

def add_frac(n1, d1, n2, d2):
    n = n1*d2 + n2*d1
    d = d1*d2
    g = mygcd(n, d)
    return n//g, d//g
person Edouard Thiel    schedule 20.11.2020
comment
Я получаю (13, 4) за add_frac(1,1,3,4) (должно быть (7,4)). Может быть, вам нужно поймать частный случай? - person Tom; 20.11.2020
comment
Это прекрасно работает, но не работает, когда можно упростить вдвое. например (1, 2, 1, 6). Это дает (4, 6), но должно давать (2, 3). Любой способ получить это? - person David; 20.11.2020
comment
на самом деле, я вычислил gcd перед суммированием; исправлено - person Edouard Thiel; 23.11.2020

Вам нужно разделить его на НОД.

import math
def add_frac(n1, d1, n2, d2):
    nume = (n1 * d1) + (n2 * d2)
    deno = d1 * d2
    gcd = math.gcd(nume,deno)
    nume /= gcd
    deno /= gcd
    return (nume,deno)

>>> add_frac(1,2,1,4)
>>> (3.0, 4.0)
person venky__    schedule 20.11.2020

Простая форма сложения двух дробей возвращает правильный ответ, но не самый сокращенный правильный ответ. Для этого нужно разделить числитель и знаменатель результата на наибольший общий знаменатель (НОД) исходных знаменателей. В этом случае НОД 2 и 4 равен 2, поэтому деление 6 и 8 на 2 дает желаемый ответ (3,4)

math.gcd можно использовать:

from math import gcd


def add_frac(n1, d1, n2, d2):
    x = gcd(d1, d2)
    frac = (((n1 * d2) + (n2 * d1)) / x, (d1 * d2) / x)
    return frac

хотя похоже, что вы должны определить свою собственную реализацию gcd.

person chepner    schedule 20.11.2020
comment
Он знает, что 6/8 можно упростить до 3/4. Его вопрос об алгоритме, как этого добиться. Как получить НОД исходных знаменателей? Это также похоже на домашнее задание, поэтому он просит не использовать импортированные функции. - person Tin Nguyen; 20.11.2020
comment
Существует множество ресурсов для реализации алгоритма GCD, и если это необходимая часть решения, то это отдельный вопрос (и слишком широкий без первоначальной попытки его написать). - person chepner; 20.11.2020
comment
Я бы еще предложил сделать функцию, нормализующую дроби, иначе этот код будет дублироваться при каждой арифметической операции над дробями. - person Alexander; 20.11.2020