# Число pi [1] с произвольной точностью можно вычислить через сумму
# бесконечного знакопеременного ряда:
#
# pi = 4 * (1 - 1/3 + 1/5 - 1/7 + ...)
def calc_pi_series(n):
"""Вычисляет сумму ряда pi из n членов"""
pi = 0 # начальное приближение pi
sign = 1 # знак следующего члена ряда
for i in range(1, 2 * n + 1, 2): # i проходит от 1 до 2*n+1 (не включая
# последний) с шагом 2
d = 4 * (1.0 / i)
pi += sign * d
sign *= -1
return pi
print("calc_pi_series(10) =", calc_pi_series(10)) # 3.04183961893
print("calc_pi_series(20) =", calc_pi_series(20)) # 3.09162380667
print("calc_pi_series(50) =", calc_pi_series(50)) # 3.12159465259
# Слишком мало точных знаков! Напишем функцию которая явно вычисляет pi с
# точностью до определённого знака.
# Нам понадобится функция count [2] из стандартной библиотеки из модуля
# itertools. Импортируем её в наш модуль:
from itertools import count
# count(st, step) генерирует числа [st, st + step, st + 2 * step, ...]
def calc_pi(digits):
"""Вычисляет pi с точностью до n-го знака.
Погрешность +/- половина знака с номером digits.
Возвращает кортеж (пи, число выполненных шагов).
"""
pi = 0 # начальное приближение pi
sign = 1
for i in count(1, 2): # числа начиная с 1 и с шагом 2
d = 4 * (1.0 / i)
pi += sign * d
sign *= -1
if d < 0.5 * 10**-digits:
# Колебания знакопеременного ряда меньше половины величины
# последней требующейся значащей цифры pi.
break;
# Возвращаем кортеж (tuple).
return (pi, (i - 1) / 2)
for digit in range(6):
print("calc_pi(" + str(digit) + ") =", calc_pi(digit))
# Задания:
#
# 1. Напишите функцию calc_e_series(n), которая будет вычислять сумму первых n
# членов ряда разложения числа e [3]:
# e = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + ...
# где символом "!" обозначен факториал.
#
# 2. Напишите функцию calc_e(digits), которая будет вычислять e с точностью
# до определённого знака. Остаток ряда оценить значением последнего
# вычисленного приращения, т.е. ряд нужно считать до первого члена, который
# окажется меньше 0.5 * 10**-digits.
#
# 3. Дана вещественная функция:
def f(x):
return -x**5 + 30 * x**3 - 1
# f(x) принимает следующие значения:
# f(-1) == -30
# f(+1) == 28
# Из того, что функция на концах отрезка [-1, 1] принимает значения разного
# знака следует, что в отрезке [-1, 1] f(x) содержит корень x0: f(x0) == 0.
#
# Необходимо написать функцию find_root(f, x_from, x_to, precision), которая
# находит корень f(x) в отрезке [x_from, x_to] методом половинного деления [4]
# с точностью precision.
#
# find_root должна сначала проверить, что на границах отрезка [x_from, x_to]
# f(x) принимает значения разного знака. Далее необходимо вычислить значение в
# середине отрезка x' = (x_from + x_to) / 2.0. Если f(x') == 0, то корень
# найден. Если f(x') того же знака, что и f(x_from), то корень находится в
# отрезке [x', x_to], иначе корень в отрезке [x_from, x'] --- длина отрезка,
# содержащего корень, сократилась в два раза. Будем продолжать искать корень на
# сокращённом отрезке до тех пор, пока длина отрезка не станет меньше
# precision, тогда в качестве корня можно вернуть значение середины последнего
# отрезка.
#
# Выведите найденное значение корня и значение функции в нём. Попробуйте искать
# корни различных несложных функций.
# Ссылки:
# [1] Число Пи: <https://ru.wikipedia.org/wiki/Пи_(число)>
# [2] itertools.count(): <http://docs.python.org/3/library/itertools.html#itertools.count>
# [3] Число e: <https://ru.wikipedia.org/wiki/E_(число)>
# [4] Метод половинного деления: <https://ru.wikipedia.org/wiki/Метод_половинного_деления>