marc lincoln
marc lincoln

Reputation: 1571

Python program to calculate harmonic series

Does anyone know how to write a program in Python that will calculate the addition of the harmonic series. i.e. 1 + 1/2 +1/3 +1/4...

Upvotes: 8

Views: 28049

Answers (11)

Mostafa Ayaz
Mostafa Ayaz

Reputation: 478

By using the numpy module, you can also alternatively use:

import numpy as np
def HN(n):
    return sum(1/arange(1,n+1))

Upvotes: 0

georgegkas
georgegkas

Reputation: 427

I add another solution, this time using recursion, to find the n-th Harmonic number.

General implementation details

Function Prototype: harmonic_recursive(n)

Function Parameters: n - the n-th Harmonic number

Base case: If n equals 1 return 1.

Recur step: If not the base case, call harmonic_recursive for the n-1 term and add that result with 1/n. This way we add each time the i-th term of the Harmonic series with the sum of all the previous terms until that point.

Pseudocode

(this solution can be implemented easily in other languages too.)

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

Python code

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

Upvotes: 0

srikar saggurthi
srikar saggurthi

Reputation: 49

Using the simple for loop

def harmonicNumber(n):
x=0
for i in range (0,n):
    x=x+ 1/(i+1)
return x

Upvotes: 0

FutureNerd
FutureNerd

Reputation: 799

A fast, accurate, smooth, complex-valued version of the H function can be calculated using the digamma function as explained here. The Euler-Mascheroni (gamma) constant and the digamma function are available in the numpy and scipy libraries, respectively.

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)


Here's a comparison of the three methods for speed and precision (with Kiv_H for reference):

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

Upvotes: 6

jfs
jfs

Reputation: 414615

@Kiv's answer is correct but it is slow for large n if you don't need an infinite precision. It is better to use an asymptotic formula in this case:

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)

@Kiv's answer for Python 2.6:

from fractions import Fraction

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

Example:

>>> 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

At N = 100 relative error is less then 1e-15.

Upvotes: 22

Kiv
Kiv

Reputation: 32738

@recursive's solution is correct for a floating point approximation. If you prefer, you can get the exact answer in Python 3.0 using the fractions module:

>>> 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)

Note that the number of digits grows quickly so this will require a lot of memory for large n. You could also use a generator to look at the series of partial sums if you wanted to get really fancy.

Upvotes: 13

joel.neely
joel.neely

Reputation: 30943

Just a footnote on the other answers that used floating point; starting with the largest divisor and iterating downward (toward the reciprocals with largest value) will put off accumulated round-off error as much as possible.

Upvotes: 6

duffymo
duffymo

Reputation: 308938

Homework?

It's a divergent series, so it's impossible to sum it for all terms.

I don't know Python, but I know how to write it in 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;
     }
 }

Upvotes: 0

zenazn
zenazn

Reputation: 14345

How about this:

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

where 1000000 is the upper bound.

Upvotes: 0

dancavallaro
dancavallaro

Reputation: 13337

The harmonic series diverges, i.e. its sum is infinity..

edit: Unless you want partial sums, but you weren't really clear about that.

Upvotes: 4

recursive
recursive

Reputation: 86124

This ought to do the trick.

def calc_harmonic(n):
    return sum(1.0/d for d in range(2,n+1))

Upvotes: 3

Related Questions