2015-02-24 2 views
1

Итак, я должен приблизиться к Pi следующим образом: 4 * (1-1/3 + 1/5-1/7 + 1/9 -...). Также он должен основываться на количестве итераций. Таким образом, функция должна выглядеть следующим образом:Python Pi аппроксимация

>>> piApprox(1) 
4.0 
>>> piApprox(10) 
3.04183961893 
>>> piApprox(300) 
3.13825932952 

Но это работает так:

>>> piApprox(1) 
4.0 
>>> piApprox(10) 
2.8571428571428577 
>>> piApprox(300) 
2.673322240709928 

Что я делаю неправильно? Вот код:

def piApprox(num): 
    pi=4.0 
    k=1.0 
    est=1.0 
    while 1<num: 
     k+=2 
     est=est-(1/k)+1/(k+2) 
     num=num-1 

    return pi*est 
+0

Try 'piApprox (2)'. –

+0

@ScottHunter 'piApprox (2)' выдает '3.466666666666667' –

+0

Вы уверены, что' piApprox (300) 'должен возвращать' 3.13825932952'? Потому что это не PI. Формула, однако, работает - если правильно реализована. –

ответ

1

Это то, что вы вычисления:

4*(1-1/3+1/5-1/5+1/7-1/7+1/9...) 

Вы можете это исправить, просто добавив k += 2 в конце вашего цикла:

def piApprox(num): 
    pi=4.0 
    k=1.0 
    est=1.0 
    while 1<num: 
     k+=2 
     est=est-(1/k)+1/(k+2) 
     num=num-1 
     k+=2 
    return pi*est 

Также, как вы считаете свои итерации, неправильно, так как вы добавляете два элемента в то время.

Это уборщик версия, которая возвращает результат, который вы ожидаете на 10 и 300 итераций:

def approximate_pi(rank): 
    value = 0 
    for k in xrange(1, 2*rank+1, 2): 
     sign = -(k % 4 - 2) 
     value += float(sign)/k 
    return 4 * value 

Вот тот же код, но более компактный:

def approximate_pi(rank): 
    return 4 * sum(-float(k%4 - 2)/k for k in xrange(1, 2*rank+1, 2)) 
+0

Все еще не дает мне необходимого ответа на проблему. Он должен делать 'piApprox (10)' и выдавать '3.04183961893', но он выдает' 3.1941879092319425' –

+0

Отредактированная версия действительно возвращает '3.1382593295155914' за 300 итераций. Таким образом, это не числовой шум, ведущий к отклонению. Вывод состоит в том, что формула не является хорошим способом численного приближения PI. - edit: действительно, я добавил это к моему ответу. –

0
def piApprox(num):                
    pi=4.0                  
    k=3.0                  
    est=1.0                  
    while 1<num:                 
    est=est-(1/k)+1/(k+2)             
    num=num-1                
    k+=4                  

    return pi*est 

Кроме того, для real task use math.pi

0

Важные правки: кто бы ни ожидал этого приближения мация для получения PI - цитата из Wikipedia:

Он сходится довольно медленно, хотя - после 500.000 терминов, он производит только пять правильных десятичных цифр П

Оригинальный ответ: Эта является образовательным примером. Вы пытаетесь использовать ярлык и пытаетесь реализовать «осциллирующий» знак слагаемых, выполнив два шага для k в той же итерации. Однако вы настраиваете k только одним шагом на итерацию.

Обычно, по математике, с достигается осциллирующий знак. Итак, я выбрал это для более читаемой реализации:

def pi_approx(num_iterations): 
    k = 3.0 
    s = 1.0 

    for i in range(num_iterations): 
     s = s-((1/k) * (-1)**i) 
     k += 2 

    return 4 * s 

Как вы можете видеть, я изменил ваш подход немного, чтобы улучшить читаемость. Вам не нужно проверять на num в цикле while, и нет никакой особой необходимости в вашей переменной pi. Ваш est фактически является суммой, которая растет шаг за шагом, поэтому почему бы не назвать ее s («сумма» - это встроенное ключевое слово в Python). Просто умножьте сумму с 4 в конце, согласно вашей формуле.

Тест:

>>> pi_approx(100) 
3.1514934010709914 

Сближение, однако, не особенно хорошо:

>>> pi_approx(100) - math.pi 
0.009900747481198291 

Ваш ожидается выход слоеное как-то, потому что ваш piApprox(300) (должен быть 3.13825932952, в соответствии с вашими) является слишком далеко от ИП. Как вы это придумали? Возможно, это связано с накопленной числовой ошибкой?

Редактировать

Я не стал бы доверять книгу слишком много в отношении того, что функция должна возвращать через 10 и 300 итераций. Промежуточный результат, после 10 шагов, должен быть скорее свободен от числовых ошибок. Там, действительно, имеет значение, выполняете ли вы два шага от k одновременно или нет. Так что это, скорее всего, разница между моими pi_approx(10) и книгами. Для 300 итераций числовая ошибка могла сильно повлиять на результат в книге. Если это старая книга, и они внедрили свой пример в C, возможно, используя одинарную точность, то значительная часть результата может быть вызвана накоплением числовой ошибки (примечание: это яркий пример того, насколько плохо вы можете быть пораженные числовыми ошибками: повторенный сумма малых и больших значений, это не ухудшается!).

Важно то, что вы рассмотрели математику (формулу для PI), и вы внедрили рабочую версию Python, аппроксимирующую эту формулу. Это была цель обучения книги, так что идите дальше и решайте следующую проблему :-).

+0

Все еще дает неправильный вывод, посмотрите на первый ответ. –

0

Вот немного упрощенная версия:

def pi_approx(num_terms): 
    sign = 1.     # +1. or -1. 
    pi_by_4 = 1.     # first term 
    for div in range(3, 2 * num_terms, 2): # 3, 5, 7, ... 
     sign  = -sign   # flip sign 
     pi_by_4 += sign/div  # add next term 
    return 4. * pi_by_4 

который дает

>>> for n in [1, 10, 300, 1000, 3000]: 
...  print(pi_approx(n)) 

4.0 
3.0418396189294032 
3.1382593295155914 
3.140592653839794 
3.1412593202657186 
Смежные вопросы