Д. П. Кириенко. Программирование на языке Python (школа 179 г. Москвы)
В этом листочке речь пойдет о действительных числах, имеющих тип float .
Обратите внимание, что если вы хотите считать с клавиатуры действительное число, то результат, возращаемый функцией input() необходимо преобразовывать к типу float :
x = float(input())
Действительные (вещественные) числа представляются в виде чисел с десятичной точкой (а не запятой, как принято при записи десятичных дробей в русский текстах). Для записи очень больших или очень маленьких по модулю чисел используется так называемая запись “с плавающей точкой” (также называемая “научная” запись). В этом случае число представляется в виде некоторой десятичной дроби, называемой мантиссой, умноженной на целочисленную степень десяти (порядок). Например, расстояние от Земли до Солнца равно 1.496·10 11 , а масса молекулы воды 2.99·10 -23 .
Числа с плавающей точкой в программах на языке Питон, а также при вводе и выводе записавыются в виде мантиссы, затем пишется буква e , затем пишется порядок. Пробелы внутри этой записи не ставятся. Например, указанные выше константы можно записать в виде 1.496e11 и 2.99e-23 . Перед самим числом также может стоять знак минус.
Напомним, что результатом операции деления / всегда является действительное число, в то время как результатом операции // является целое число.
Преобразование действительных чисел к целому производится с округлением в сторону нуля, то есть int(1.7) == 1 , int(-1.7) == -1 .
Как приближенно вычислить значение числа Пи с использованием объема сферы?
Моя задача — вычислить приближенное значение числа Пи с точностью не менее 10^-6. Алгоритм Монте-Карло не обеспечивает требуемой точности. Мне нужно использовать расчет с использованием объема шара. Что посоветуете?
Отслеживать
13.7k 12 12 золотых знаков 43 43 серебряных знака 75 75 бронзовых знаков
задан 12 июн 2021 в 10:42
11 2 2 бронзовых знака
А чем вас Монте-Карло не устраивает собственно? Уточните.
13 июн 2021 в 8:31
Попробуйте ряд Нилаканта. и уточните что там про шар ? какие данные есть ?
13 июн 2021 в 8:42
Если критично именно сферу использовать — просто тремя циклами проходите по координатам от 0 до R, проверяйте попадает ли координата внутрь сферы. Но тогда не не будет постепенного приближения к точному значению, а нужно будет дождаться до конца выполнения всех циклов, и только потом получить результат.
13 июн 2021 в 8:57
@Asan Монте-Карло (да и любой другой алгоритм перебора) надо запускать и оставлять не до того момента, как он впервые покажет 3,141592**, а дольше. Насколько точно дольше — не подскажу, тут надо теорию вспоминать/знать ..
13 июн 2021 в 9:45
Посоветую численное интегрирование для вычисления объема шара.
15 июн 2021 в 5:58
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Приблизим осьмушку шара треугольным мешем. Вершины меша будут лежать на поверхности единичной сферы. Тело ограниченное координатными плоскостями и мешем лежит целиком внутри осьмушки шара. Его объём используем для оценки pi снизу. Отыщем множитель на который нужно умножить координаты всех вершин меша так чтобы после умножения фигура содержала осьмушку шара внутри себя. Объём новой (раздутой) фигуры используем для оценки pi сверху. Так как мы не знаем заранее сколько должно быть треугольников в меше, то будем повторять процедуру со всё более подробными мешами пока оценки pi не сблизятся на расстояние 10^-6. Поехали.
Четыре поколения поверхностей:

Начинается всё с одного треугольника. Следующая поверхность строится так: каждый треугольник предыдущей разбивается на четыре меньшего размера. Новые точки на серединах сторон оказываются под поверхностью сферы. Чтобы вернуть их на сферу их координаты нормализуются.
Объём полигонального тела складывается из объёмов тетраэдров. Тетраэдр строится на треугольнике поверхности и точке (0, 0, 0) . Шестикратный объём такого тетраэдра вычисляется как определитель.
Имеем последовательность оценок числа pi снизу. Как оценить pi сверху?
Каждый треугольник поверхности определяет плоскость. Вычислим минимальное расстояние от этой плоскости до начала координат: строим единичный нормальный вектор к треугольнику, скалярно умножаем его на координаты любой вершины треугольника. Расстояние получится меньше единицы.
Если все координаты всех вершин треугольника умножить на величину обратную к найденному расстоянию, то новые вершины образуют новую плоскость (параллельную старой), для которой расстояние будет единичным.
Выберем минимум из расстояний для всех треугольников поверхности. Все вершины поверхности домножим на обратную величину. Получим новую поверхность гомотетичную старой. Новая поверхность целиком проходит вне шара. То есть объём нового тела будет больше pi . Конечно, суммировать его заново не надо, он вычисляется из объёма поверхности внутри шара умножением на некоторый коэффициент.
import math def add(p1, p2): x1, y1, z1 = p1 x2, y2, z2 = p2 return x1 + x2, y1 + y2, z1 + z2 def sub(p1, p2): x1, y1, z1 = p1 x2, y2, z2 = p2 return x1 - x2, y1 - y2, z1 - z2 def scale(f, p): x, y, z = p return f * x, f * y, f * z def mid(p1, p2): return scale(1 / 2, add(p1, p2)) def dot(p1, p2): x1, y1, z1 = p1 x2, y2, z2 = p2 return x1 * x2 + y1 * y2 + z1 * z2 def norm(p): return math.sqrt(dot(p, p)) def normalized(p): return scale(1 / norm(p), p) def cross(p1, p2): x1, y1, z1 = p1 x2, y2, z2 = p2 return \ y1 * z2 - z1 * y2, \ z1 * x2 - x1 * z2, \ x1 * y2 - y1 * x2 def normal(p1, p2, p3): return normalized(cross(sub(p2, p1), sub(p3, p1))) def height(p1, p2, p3): return dot(normal(p1, p2, p3), p1) def volume6(p1, p2, p3): x1, y1, z1 = p1 x2, y2, z2 = p2 x3, y3, z3 = p3 # | x1, y1, z1 | # | x2, y2, z2 | # | x3, y3, z3 | return \ ((x1 * y2) - (x2 * y1)) * z3 - \ ((x1 * y3) - (x3 * y1)) * z2 + \ ((x2 * y3) - (x3 * y2)) * z1 def subdiv(p1, p2, p3): p12 = normalized(mid(p1, p2)) p23 = normalized(mid(p2, p3)) p31 = normalized(mid(p3, p1)) yield p1, p12, p31 yield p2, p23, p12 yield p3, p31, p23 yield p12, p23, p31 def main(): surface = (((1, 0, 0), (0, 1, 0), (0, 0, 1)), ) for i in range(1, 1000): print(f'(): ', flush=True, end='') min_height = min(height(*t) for t in surface) v_low = sum(volume6(*t) for t in surface) v_high = v_low * (1 / min_height) ** 3 print(f' < pi < , ') if v_high - v_low < 1e-6: break surface = tuple(tt for t in surface for tt in subdiv(*t)) main()
$ time python pi_approximation.py 1(1): 1 < pi < 5.196152422706629, 4.196152422706629 2(4): 2.207106781186547 < pi < 4.054714066307733, 1.8476072851211862 3(16): 2.8632972148712703 < pi < 3.4166084802548, 0.5533112653835297 4(64): 3.0687004650644996 < pi < 3.2136638054952016, 0.14496334043070203 5(256): 3.123152697186476 < pi < 3.1598235333433777, 0.03667083615690192 6(1024): 3.136968953405614 < pi < 3.1461637781466827, 0.009194824741068697 7(4096): 3.140435869168335 < pi < 3.142736273849948, 0.0023004046816126333 8(16384): 3.1413034037353573 < pi < 3.141878611120626, 0.0005752073852685058 9(65536): 3.141520337766175 < pi < 3.1416641462518413, 0.00014380848566641902 10(262144): 3.1415745744239363 < pi < 3.141610526960324, 3.595253638755125e-05 11(1048576): 3.1415881337850373 < pi < 3.141597121945071, 8.988160033585046e-06 12(4194304): 3.141591523637882 < pi < 3.141593770679511, 2.2470416292108553e-06 13(16777216): 3.141592371100547 < pi < 3.1415929328610557, 5.617605087770983e-07 real 2m59.102s user 2m57.320s sys 0m1.480s
Ищем значение числа Пи, используя генератор случайных значений
В первую секунду может показаться, что ваш интервьюер слегка издевается над вам, но если вспомнить основы из теории вероятности, то все становится гораздо проще. Let's go!
База из теории вероятности
Классическое определение вероятности.
Вероятность, что событие A произойдет, равно отношению количеству благоприятных исходов к количеству всех возможных исходов
На языке математики это выглядит так:
Например у нас есть кубик. Какая вероятность что выпадет грань с четными значениями?
Набор всех исходов <>
Набор благоприятных исходов <>
Значит
Геометрическое определение вероятности.
Предыдущее определение вероятности отличное, но оно обладает несколькими существенными ограничениями. Одним из таких ограничений является тот факт, что оно неприменимо к испытаниям с бесконечным количеством исходов.
Чтобы стало понятно о чем речь - давайте решим задачку.
На отрезок случайным образом брошена точка Найдите вероятность того, что она попадет в промежуток
Понятно, что здесь не получится использовать классическое определение, поскольку на отрезке бесконечно много точек. Тогда нам идет на помощь геометрическое определение
вероятности , в нашем случае ,
Решение задачи
Концепция
Построим геометрическую модель.
Введем систему координат с осями и
Расположим квадрат с единичной стороной, так чтобы начало системы координат находилось в левом углу.
Нарисуем единичный круг с центром в начале координат.

Будем случайным образом располагать точку в квадрате.
Наша исходная задача сводится к следующему вопросу.
Какая вероятность, что точка попадет в верхнюю правую четверть круга (область A)
Мы знаем, что , а
Значит вероятность того, что точка попадет в искомую область равна
С другой стороны, после распределения n точек по квадрату, мы можем оценить количество точек, которое попало внутрь круга. Для этого точка с координатами
должна удовлетворять неравенству
Тогда вероятность , где количество точек попавших внутрь круга, а n общее число точек.
Значит из верних соотношений имеем
Программируем
import random def estimate_pi(n): num_point_circle = 0 #кол-во точек внутри круга num_point_total = n for i in range(n): x = random.uniform(0,1) y = random.uniform(0,1) distance = x**2 + y**2 if distance
На этом все!
Надеюсь вам понравилась задача! Делитесь своими интересными задачками с собеседований, будем разбирать)
Связаться со мной @polozovs
Какая функция нужна для числа пи в Python?
Число Пи может быть вызвано с помощью константы pi встроенного в Python пакета math.
import math # для использования функции импортировать библиотеку math print(math.pi) # => 3.141592653589793
11 апреля 2023
Мало ли кому интересно. Формула для вычисления любого количества знаков после запятой на питоне.
epsilon: n += 1 arith = (a + b)/2 geom = sqrt(a*b) a, b = arith, geom series += 2**(n+1) * (a*a - b*b) diff = a - b # a and b have converged to the AGM my_pi = 4*a*a/(1 - series) error = fabs(pi - my_pi) decimal_places = int(-log10(error)) print("Number of steps used: %d" % n) print("Number of correct decimal places: %d" % decimal_places) print(pi)