Программа Python для расчета гармонических рядов - PullRequest
5 голосов
/ 01 января 2009

Кто-нибудь знает, как написать программу на Python, которая будет вычислять сложение гармонического ряда? то есть 1 + 1/2 +1/3 +1/4 ...

Ответы [ 10 ]

21 голосов
/ 01 января 2009

@ Kiv's ответ правильный, но медленный для больших n, если вам не нужна бесконечная точность. В этом случае лучше использовать асимптотическую формулу :

asymptotic expansion for harmonic number

#!/usr/bin/env python
from math import log

def H(n):
    """Returns an approximate value of n-th harmonic number.

       http://en.wikipedia.org/wiki/Harmonic_number
    """
    # Euler-Mascheroni constant
    gamma = 0.57721566490153286060651209008240243104215933593992
    return gamma + log(n) + 0.5/n - 1./(12*n**2) + 1./(120*n**4)

@ ответ Кива для Python 2.6:

from fractions import Fraction

harmonic_number = lambda n: sum(Fraction(1, d) for d in xrange(1, n+1))

Пример:

>>> N = 100
>>> h_exact = harmonic_number(N)
>>> h = H(N)
>>> rel_err = (abs(h - h_exact) / h_exact)
>>> print n, "%r" % h, "%.2g" % rel_err
100 5.1873775176396242 6.8e-16

При N = 100 относительная ошибка меньше 1e-15.

12 голосов
/ 01 января 2009

@ рекурсивное решение верно для приближения с плавающей запятой. Если вы предпочитаете, вы можете получить точный ответ в Python 3.0, используя модуль фракций:

>>> from fractions import Fraction
>>> def calc_harmonic(n):
...   return sum(Fraction(1, d) for d in range(1, n + 1))
...
>>> calc_harmonic(20) # sum of the first 20 terms
Fraction(55835135, 15519504)

Обратите внимание, что число цифр быстро растет, поэтому для больших n потребуется много памяти. Вы также можете использовать генератор, чтобы посмотреть серию частичных сумм, если вы хотите по-настоящему модно.

5 голосов
/ 01 января 2009

Просто сноска на другие ответы, которые использовали с плавающей запятой; начиная с самого большого делителя и итерируя вниз (по направлению к обратным значениям с наибольшим значением), вы максимально отклоните накопленную ошибку округления.

4 голосов
/ 29 декабря 2014

Быстрая, точная, гладкая, комплексная версия H-функции может быть рассчитана с использованием функции дигаммы, как описано здесь . Константа Эйлера-Мачерони (гамма) и функция digamma доступны в библиотеках numpy и scipy, соответственно.

from numpy import euler_gamma
from scipy.special import digamma

def digamma_H(s):
    """ If s is complex the result becomes complex. """
    return digamma(s + 1) + euler_gamma

from fractions import Fraction

def Kiv_H(n):
    return sum(Fraction(1, d) for d in xrange(1, n + 1))

def J_F_Sebastian_H(n):
    return euler_gamma + log(n) + 0.5/n - 1./(12*n**2) + 1./(120*n**4)


Вот сравнение трех методов для скорости и точности (с Kiv_H для справки):

Kiv_H(x) J_F_Sebastian_H(x) digamma_H(x) x seconds bits seconds bits seconds bits 1 5.06e-05 exact 2.47e-06 8.8 1.16e-05 exact 10 4.45e-04 exact 3.25e-06 29.5 1.17e-05 52.6 100 7.64e-03 exact 3.65e-06 50.4 1.17e-05 exact 1000 7.62e-01 exact 5.92e-06 52.9 1.19e-05 exact

4 голосов
/ 01 января 2009

Ряд гармоник расходится, т. Е. Его сумма равна бесконечности.

edit: Если вам не нужны частичные суммы, но вы не совсем понимаете это.

2 голосов
/ 01 января 2009

Это должно сработать.

def calc_harmonic(n):
    return sum(1.0/d for d in range(2,n+1))
0 голосов
/ 20 мая 2017

Я добавляю другое решение, на этот раз используя рекурсию, чтобы найти n-й номер гармоники.

Общая информация о реализации

Прототип функции: harmonic_recursive(n)

Параметры функции: n - номер n-й гармоники

Базовый случай: Если n равно 1, вернуть 1.

Повторный шаг: Если не базовый случай, вызовите harmonic_recursive для термина n-1 и добавьте полученный результат с 1/n. Таким образом, мы каждый раз добавляем i-й член ряда Гармоник с суммой всех предыдущих членов до этой точки.

псевдокод

(это решение может быть легко реализовано и на других языках.)

harmonic_recursive(n):
    if n == 1:
        return 1
    else:
        return 1/n + harmonic_recursive(n-1)

код Python

def harmonic_recursive(n):
    if n == 1:
        return 1
    else:
        return 1.0/n + harmonic_recursive(n-1)
0 голосов
/ 30 января 2017

Использование простого цикла for

def harmonicNumber(n):
x=0
for i in range (0,n):
    x=x+ 1/(i+1)
return x
0 голосов
/ 01 января 2009

Домашнее задание?

Это расходящийся ряд, поэтому его невозможно суммировать по всем терминам.

Я не знаю Python, но я знаю, как написать его на Java.

public class Harmonic
{
    private static final int DEFAULT_NUM_TERMS = 10;

    public static void main(String[] args)
    {
        int numTerms = ((args.length > 0) ? Integer.parseInt(args[0]) : DEFAULT_NUM_TERMS);

        System.out.println("sum of " + numTerms + " terms=" + sum(numTerms));
     }

     public static double sum(int numTerms)
     {
         double sum = 0.0;

         if (numTerms > 0)
         {
             for (int k = 1; k <= numTerms; ++k)
             {
                 sum += 1.0/k;
             }
         }

         return sum;
     }
 }
0 голосов
/ 01 января 2009

Как насчет этого:

partialsum = 0
for i in xrange(1,1000000):
    partialsum += 1.0 / i
print partialsum

, где 1000000 - верхняя граница.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...