2013-09-23 2 views
3
def wallis(n): 
    pi = 0.0 

    for i in range(n): 
     left = (2 * i)/(2 * i - 1) 
     right = (2 * i)/(2 * i + 1) 
     total = left * right 
     pi = pi + total 

    return pi 

print wallis(1000) 
print wallis(10000) 
print wallis(100000) 

Я скопировал формулу точно, но я продолжаю получать 0 в качестве вывода. Может кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно. Python 2.7.Формула Уоллиса для pi

Ссылка на формуле here

+0

В Python 2.7, 2/3 является целым числом фактор, таким образом, 0. Вы должны сделать поплавок (2)/3 или 2/поплавок (3), так что в по меньшей мере один операнд - это float, чтобы получить коэффициент float. Опасайтесь: в Python 3, 2/3 - результат поплавка, вам нужно написать 2 // 3, чтобы получить целочисленное частное. –

+1

Не нужно вычислять. Согласно [Indiana Pi bill] (http://en.wikipedia.org/wiki/Indiana_Pi_Bill), это 3.2. И это O (1), чтобы вычислить! –

ответ

7

Python делает целочисленное деление, и обрезает десятичные. Это связано с тем, что оба значения деления являются целыми числами. Преобразуйте одно из чисел в float, чтобы получить возвращаемое значение с плавающей запятой.

left = float(2 * i)/(2 * i - 1) 
right = float(2 * i)/(2 * i + 1) 

или, как @kindall указывает, вы можете изменить константы поплавки непосредственно и избежать вызов функции float:

left = (2.0 * i)/(2 * i - 1) # just 2. works, too 
right = (2.0 * i)/(2 * i + 1) 

Если/когда вы переключаетесь на Python 3 .x, вам не нужно это делать. На самом деле вам нужно явно запросить целочисленное деление с //.

В соответствии с замечанием @Serdalis, вы также можете добавить from __future__ import division в верхней части файла, чтобы получить такое же поведение, как питон 3.x (то есть вам не нужно будет добавить float в вашем уравнении.)

+0

Так что я должен придумать проблему, так сказать ... Я привык к C и просто изучаю Python. Я делаю что-то математически неправильно с моей программой. Я могу понять эту часть. Большое спасибо. – juice

+0

IIRC '//' целочисленный оператор разделения доступен в Python 2.7 (даже без 'from __future__') и, вероятно, должен использоваться, когда вы действительно хотите целое число. Причины - быть более явными и лучше подготовленными для Python 3.x. Мне больно говорить, что, хотя, я все еще думаю, что было сумасшедшим изменить семантику арифметического оператора. – Steve314

+0

@juice Нет проблем. В терминах C, я полагаю, это похоже на приведение типов.Это необходимо только в python при выполнении деления с двумя целыми числами и только в python 2.x. – SethMMorton

4

Помимо проблемы, обозначенной @SethMMorton, ваша формула неверна. Сначала это продукт не сумма, второй - pi/2, а не pi. В конце концов нет оснований петли от 0.

def wallis(n): 
    pi = 2. 
    for i in xrange(1, n): 
     left = (2. * i)/(2. * i - 1.) 
     right = (2. * i)/(2. * i + 1.) 
     pi = pi * left * right 
    return pi 
1

Просто добавить, что вы можете сделать это в вещем образом, что также выглядит намного ближе к математическому выражению. (Здесь +0,25 заботится о преобразовании с плавающей запятой)

def product(iterator): 
    return reduce(lambda x, y: x * y, iterator) 

print 2 * product(i * i/(i * i - .25) for i in xrange(1, 1000)) 
1

Согласно формуле Уоллис:

enter image description here

... и с реализацией в Python 3.4.2 общее время выполнения из ~0.095s для n = 100000:

def wallis(n): 
    pi = 0.0 
    for i in range(1, n): 
     x = 4 * (i ** 2) 
     y = x - 1 
     z = float(x)/float(y) 
     if (i == 1): 
      pi = z 
     else: 
      pi *= z 
    pi *= 2 
    return pi 

print(wallis(100000)) 
+0

. Было бы лучше, если бы вы включили краткое объяснение, почему/как это работает. – iCodez

0

Еще одно решение, используя список Встроенные функции и список ком схватывание на максимум "pythonicness" :)

2 * reduce(lambda x, y: x*y, [(4.0*(i**2))/(4.0*(i**2)-1) for i in range (1, 1000000)]) 
Смежные вопросы