Кто-нибудь знает, как кодировать ряд гармоник в python?

H(n) = 1 + 1/2 + 1/3 + ... + 1/n

Примечание: нам не разрешено импортировать из предопределенных модулей. Выходными данными должны быть числитель и знаменатель ответа в виде дроби (самые низкие условия).

Так вот мой код для этого гармонического ряда.

n = input("Enter n:")  

def harmonic(n):  
    a=1  
    b=1  
    for d in range(2, n+1):  
            a = a*d+b  
            b = b*d  
            return (a,b)  
            x == max(a,b)%min(a, b)  
            if x == 0:  
                y=min(a,b)  
                return y  
            else:  
                y=min(a,b)/x  
                return y  
            a=a/y  
            b=b/y  
            return (a,b)  
print harmonic(n)  

В чем дело? Что бы я ни вводил, вывод всегда (3,2)

1
user1950302 22 Янв 2013 в 13:59

5 ответов

Лучший ответ

Я должен проверить вашу попытку дважды - и вставил простой gcd (в середине вашего исходного кода)

n = input("Enter n:")

def harmonic(n): #original harmonic series
     a=1
     b=1
     for d in range(2, n+1):
         a = a*d+b
         b = b*d
     return(a,b)


def harmonic_lt(n): #_lt: harmonic series with lowest terms
                    #not pythonic, but simple
    a=1
    b=1
    for d in range(2, n+1):
        a = a*d+b
        b = b*d

    y=a
    x=b
    while x > 0:
        re = y % x
        y = x
        x = re

    a=a/y
    b=b/y
    return(a,b)

print harmonic(n)
print harmonic_lt(n)
2
Excalibur 22 Янв 2013 в 22:15

Вы можете найти знаменатель, найдя наименьшее общее кратное чисел 1..n.

Номинатор будет тогда суммой всех значений denominator/x, где x будет всеми значениями из 1..n.

Вот код:

def gcd(a, b):
    """Return greatest common divisor using Euclid's Algorithm."""
    while b:      
        a, b = b, a % b
    return a

def lcm(a, b):
    """Return lowest common multiple."""
    return a * b // gcd(a, b)

def lcmm(args):
    """Return lcm of args."""   
    return reduce(lcm, args)


def harmonic(n):
    lowest_common_multiple = lcmm(range(1,n))
    nominator = sum([lowest_common_multiple/i for i in range(1,n)])
    greatest_common_denominator = gcd(lowest_common_multiple, nominator)
    return nominator/greatest_common_denominator, lowest_common_multiple/greatest_common_denominator

print harmonic(7)
print harmonic(10)
print harmonic(20)
1
Thorsten Kranz 22 Янв 2013 в 11:48

Вы всегда возвращаете (a, b) на первой итерации. - Шаррон "

Возврат всегда завершает функцию. Если вы вернете (a, b), остальная часть кода будет недоступна

0
Gjordis 22 Янв 2013 в 10:05

Гармоническая серия:

1/1 + 1/2 + ... + 1/n == (n!/1 + n!/2 + ... + n!/n)/n!

Поэтому вы можете сделать:

nom = reduce(lambda s, x: s*x, xrange(1, n+1),1)   # n!
denom = sum([nom / x for x in xrange(1, n+1)])

Затем вам нужно выполнить gcd-сокращение для nom и denom.
Используйте версию от Торстена Кранца.

Обратите внимание, что для этого нужен только один вызов gcd!

Пример:

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


def harmonic(n):
    nom = reduce(lambda s, x: s*x, xrange(1,n+1), 1)   # n!
    denom = sum([nom / x for x in xrange(1, n+1)])
    f = gcd(denom, nom)
    return (denom / f), (nom / f)


print harmonic(10)
print harmonic(20)

(7381, 2520)
(55835135, 15519504)
1
Theodros Zelleke 22 Янв 2013 в 14:01

Как отмечали другие, вы возвращаетесь, когда d = 2, то есть (1 + 1/2), оно должно быть вне цикла for.

Вот код, который я написал для того же:

#!Python2.7
def gcd(a, b):
    if b: return gcd(b, a%b)
    return a

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

def start():
    n = int(raw_input())
    ans = reduce(lambda x, y: (x[0]*lcm(x[1],y[1])/x[1]+y[0]*lcm(x[1],y[1])/y[1], lcm(x[1],y[1])),[(1,x) for x in xrange(1,n+1)])
    _gcd = gcd(ans[0], ans[1])
    print (ans[0]/_gcd, ans[1]/_gcd)

start()

Если вы хотите избежать использования reduce, lamda и составить список:

#!Python2.7
def gcd(a, b):
    if b: return gcd(b, a%b)
    return a

def lcm(a, b):
    assert a != 0
    assert b != 0
    return a*b/gcd(a, b)

def next(x, y):
    lcmxy = lcm(x[1], y[1])
    return (x[0]*lcmxy/x[1]+y[0]*lcmxy/y[1], lcmxy)

def start():
    n = int(raw_input())
    curr = (1,1)
    for x in xrange(2,n+1):
        curr = next(curr, (1,x))
    _gcd = gcd(curr[0], curr[1]) 
    print (curr[0]/_gcd, curr[1]/_gcd)

start()
1
sidi 22 Янв 2013 в 10:47