«И сделал литое из меди море – от края его до края его десять локтей – совсем круглое, высотой в пять локтей, и шнурок в тридцать локтей обнимал его кругом»
(3-я Царств 7:23)
В эпиграфе приведён текст из Священного писания, из которого прямо следует, что отношение длины окружности к её диаметру, также известное, как «число π» равно точно трём. Надеюсь, никто из присутствующих не намерен подвергать сомнению истинность священных текстов? Домыслы же еретиков и отступников про какую-то там иррациональность, есть не что иное, как гнусное фарисейство и сатанинская ересь, ожидающие Суда Святой Инквизиции.
Однако, поскольку эта ересь получила весьма широкое распространение, я решил развеять её в прах прямым расчётом этого проклятого числа. Просто посчитать его в лоб, чтобы уж ни у кого не оставалось никаких сомнений.
Таким образом, цель настоящего исследования – посрамить фарисеев и отступников и, в меру моих скромных сил, укрепить и возвысить сияющую истинность Священного Писания. Конечно же, она (истинность) настолько абсолютна и бесспорна, что не нуждается ни в каких моих «подтверждениях»! Зато я остро нуждаюсь в том, чтобы служить ей, всемерно благословлять её, и разбивать в пух и прах любые еретические, псевдонаучные построения. Чем я сейчас, помолясь, и займусь.
Итак, число π мы будем считать методом Монте-Карло (ну, а каким ещё способом его можно считать в пятницу, тринадцатого числа?).
Суть метода, для тех, кто с ним незнаком, такова:
Нарисуем в координатных осях единичный квадрат (на рисунке – пунктиром) и нарисуем четверть круга с радиусом равным единице и центром в начале координат (на рисунке – закрашен серым).
Очевидно, что площадь единичного квадрата равна единице, а площадь четверти круга единичного радиуса равна π/4. Тогда, если мы «набросаем» в этот квадрат достаточно много случайных точек, то отношение количества точек, попавших внутрь круга, к общему количеству «набросанных» точек будет приблизительно равно π/4. Причем, это будет тем точнее, чем больше случайных точек мы туда набросаем.
Собственно всё, осталось умножить полученную величину на 4 и получим приближение числа π, тем более точное, чем больше точек мы туда «набросали».
Нам потребуется функция для генерации псевдослучайных координат точек в диапазоне от 0 до 1. Ничего особенного, вот она:
Реализация
static inline double rndXY(void) {
constexpr long lMax = 1000000;
constexpr double dMax = lMax;
return random(lMax) / dMax;
}
Также, нам потребуется функция для проверки попала точка с заданными координатами внутрь круга или не попала. Опять же, ничего особенного, просто по двум координатам, которые являются катетами прямоугольного треугольника, считаем гипотенузу (по теореме Пифагора). Если гипотенуза меньше единицы, то точка попала в круг, иначе - не попала.
Реализация
bool check(const double x, const double y) {
return x * x + y * y < 1;
}
Ну и собираем всё вместе.
Полный код
//
// Возвращает true, если точка (x,y) попадает
// внутрь единичной окружности и fals в противном случае
//
bool check(const double x, const double y) {
return x * x + y * y < 1;
}
//
// Генерирует псевдослучайное число от 0 до 1
// с шестью разумными знаками после запятой
//
static inline double rndXY(void) {
constexpr long lMax = 1000000;
constexpr double dMax = lMax;
return random(lMax) / dMax;
}
void setup(void) {
Serial.begin(9600);
//
// Проводим totalTests проб, попадает ли случайная точка
// внутрь единичной окружности и сохраняем количество попаданий
// в переменной col
//
constexpr int totalTests = 10000; // хватит. можно и больше
long col=0;
for (int i=0; i < totalTests; col+=check(rndXY(),rndXY()),i++);
//
// Считаем и печатаем число ПИ
// Не забываем, что оно с плавающей точкой!
//
const double thePi = 4 * col / totalTests;
Serial.print("PI = ");
Serial.println(thePi);
}
void loop(void) {}
Запускаем и получаем результат
PI = 3.00
что, собственно, и требовалось доказать!
Всех с пятницей - 13-ым!