2013-02-22 7 views
0
pi/2 = 1 + 1/3 + (1*2)/(3*5) + (1*2*3)/(3*5*7) + ... 

Bon, essayons encore ceci.Utilisation d'une série pour calculer pi en Python

J'ai besoin d'écrire une fonction qui prend l'erreur maximale en tant que paramètre pour la valeur de pi et renvoie la valeur calculée de pi et le nombre d'itérations nécessaires pour arriver à ce point. Je ne peux pas utiliser un algorithme récursif.

Jusqu'à présent j'ai:

def piEuler (x): 
    count = 0.0 
    approx = 0.0 
    approx2 = 1.0 
    error = math.pi/2 - approx2 
    while error > x: 
     count = count + 1 
     approx3 = approx + approx2 
     error = math.pi/2 - approx3 
     #print error 
     approx = approx + approx2 
     approx2 = approx2 * count/(count + 2) 
     #print approx2 
    final = math.pi - error 
    return final, count 

Le problème est que le programme renvoie une valeur négative. L'erreur devrait converger vers zéro. Je dois être capable de soustraire mon erreur de la valeur acceptée de pi pour obtenir une valeur approximative de la série. Qu'est-ce que je fais mal?

+0

Les termes de votre dénominateur ne semblent pas corrects. Ne devriez-vous pas calculer le produit de '3 * 5 * ... * (2 * k + 1)' pour 'k = 1,2, .., n/2'? On dirait que vous faites 3 * 4 * 5 * ... * n'. Cela vous donnerait un plus grand nombre et expliquerait pourquoi la série est additionnée à un nombre supérieur à 'pi/2' et donc augmenter le terme d'erreur en valeur absolue (mais diminuer en valeur réelle, c'est-à-dire devenir négatif). –

+0

@JoelCornett Vous devriez publier cela comme une réponse. –

+0

@ Jon-Eric: Bon appel, posté. –

Répondre

1

Il semble que vous ayez implémenté l'algorithme de façon incorrecte. Plutôt que de faire pi/2 = 1 + 1/3 + (1*2)/(3*5) + (1*2*3)/(3*5*7) + ..., il semble que votre code fasse pi/2 = 1 + 1/3 + (1*2)/(3*4) + (1*2*3)/(3*4*5) + ....

Depuis les dénominateurs finissent par être plus petit, vous augmenterez la somme par une plus grande quantité, ce qui ne fait aucun doute dans une remise des gaz et par conséquent une erreur négative.

Le problème se trouve dans cette ligne:

approx2 = approx2 * count/(count + 2) 

Comme vous pouvez le voir, quand count est encore, count + 2 aura même. Une solution facile serait de changer cela:

approx2 = approx2 * count/(2 * count + 1) 

Voici un exemple d'algorithme qui fonctionne, mais utilise l'erreur relative entre les termes plutôt que l'erreur absolue (ne voudrait pas tout donner;)):

from __future__ import division 

def half_pi(max_err=10**-6, max_iter=10000): 
    partial_sum = cur_term = 1 
    n = 1 
    while abs(t) > max_err and n < max_iter: 
     cur_term = cur_term * (n/(2 * n + 1)) 
     partial_sum += cur_term 
     n += 1 
    return partial_sum, n 
+0

Avec le changement de l'approx2 défini et quelques bugs mineurs, cela a fonctionné parfaitement. Les nombres négatifs ne sont jamais un problème lorsque la série converge vers zéro. Cela ne deviendra infiniment plus proche. Merci beaucoup pour votre aide! –

2

Cela fonctionne:

import math 

def piEuler(x): 

    halfpi = math.pi/2.0 
    count  = 0 
    approx = 1.0 
    divisor = 1 
    numerator = 1 
    while True: 
     count  += 1 
     numerator *= count 
     divisor *= 2*count + 1 
     approx += float(numerator)/float(divisor) 
     error  = halfpi - approx 

     if error < x: 
      return (math.pi - error), count 

Les différences fondamentales sont les suivantes:

  1. En changeant la condition de terminaison de la boucle à un essai/pause, je peux retirer le calcul manuel du second terme de la série
  2. Utilisation prudente des types de données int et float (cela peut être votre problème)
  3. Une meilleure dénomination des variables facilite le débogage
0

Vous devriez essayer de réécrire la routine de sorte que le terme le plus petit dans la séquence, approx2 dans votre code, doit être supérieure à l'erreur.

Vous avez également « Math.PI. » dans votre dernier calcul d'erreur. Est-ce que ça doit être math.pi/2?

Il semble que la nature de l'erreur oscille également!

+0

Au contraire, l'erreur serait décroissante de façon monotone, étant donné que la somme partielle augmente de façon monotone. –

Questions connexes