![]() |
#1
|
|||
|
|||
![]()
Alexander A. Vorobyov написал(а) к All в May 25 23:00:54 по местному времени:
ТЕОРИЯ ОДИННАДЦАТИ "РУКОПОЖАТИЙ", ИЛИ КАК Я ЗАКРЫЛ СВОЙ ДЕТСКИЙ ГЕШТАЛЬТ Когда я был ребёнком, я любил предаваться долгим раздумьям на различные пустяковые темы. Часто я ложился поперёк дивана, закинув ноги на его спинку, а голову свесив вниз, и в таком положении о чём-нибудь размышлял. Один вопрос, который тогда весьма меня занимал, касался часов, висевших на стене напротив. Вернее, не самих часов, а их стрелок. Как обычно, вверх тормашками, я наблюдал за движением минутной стрелки, когда она приближалась к часовой, в какой-то неуловимый момент сливалась с ней в единую линию, а затем ползла дальше, оставив свою неторопливую спутницу позади. Меня удивлял тот факт, что стрелки всё-таки сходятся, ведь логика (моя тогдашняя логика) подсказывала, что пока минутная стрелка догоняет часовую, та, хоть и с гораздо меньшей скоростью, всё-таки убегает вперёд. Таким образом, расстояние между ними должно сокращаться бесконечно долго, и момент их схождения не должен наступить вовсе. И ещё -- в какой именно момент сходятся стрелки? Где эта неуловимая грань между "до" и "после"? Много позже, когда я услышал о парадоксе Ахиллеса и черепахи, я подумал, что Зенон Элейский наверняка тоже был любителем поваляться на своём древнегреческом диване вверх тормашками. Прошло время, я узнал о существовании сходящихся рядов, детское удивление исчезло. Но появилась мысль: а хорошо бы рассчитать точное время каждого схождения стрелок. Что если взять и написать программку, которая сделала бы эти расчёты? Кстати, по-английски часовые стрелки называются руками (hands), и мне нравится называть такие схождения "рукопожатиями". Много лет мысль о расчёте этих "рукопожатий" сидела едва ощутимой занозой где-то на задворках моего сознания, пока однажды на работе не приключился вынужденный простой, и я, почесав уже изрядно поседевшую небритость, решил наконец закрыть этот гештальт. Для понимания дальнейшего изложения строго рекомендуется принять положение головой вниз, ногами кверху. Сначала я решал задачу "в лоб": стал крутить воображаемые стрелки, на каждом шаге цикла считая угол между ними. Но при таком подходе приходится вводить некий диапазон углов, попав в который стрелки будут считаться сошедшимися. При неудачном выборе этого диапазона в него попадают сразу несколько положений стрелок, или вовсе ни одного. И вообще, это не изящно. Подозреваю, что именно из-за отсутствия изящества в управляющей программе в 2023 году хряпнулась о лунную поверхность станция Луна-25. Тогда я пошёл другим путём. Наблюдение 1: "рукопожатий" случается всего 11 за полный оборот часовой стрелки. Наблюдение 2: между "рукопожатиями" проходит одинаковое время -- 1 час 5 минут и ещё чуть-чуть. Наблюдение 3: минутная стрелка проходит на 360 градусов больше, чем часовая. Наблюдение 4: минутная стрелка движется в 12 раз быстрее часовой, поворачиваясь на 1 градус за 10 секунд. Собственно, этого достаточно для решения задачи. Период совмещения часовой и минутной стрелок можно описать пропорцией a / h = (a + 360) / (12h), где: a -- угол, который проходит часовая стрелка до каждого следующего "рукопожатия"; h -- скорость движения часовой стрелки; (a + 360) -- угол, который проходит минутная стрелка; 12h -- скорость минутной стрелки. По сути, здесь слева записано время от одного "рукопожатия" до следующего для часовой стрелки, а справа -- для минутной. Разумеется, это одно и то же время, значит мы имеем право поставить знак равенства. Чуть-чуть математики за 5-й класс: a12*h = h(a + 360) 12a = a + 360 11a = 360 a = 360 / 11 = 32,(72) градуса. Раз минутная стрелка поворачивается на 1 градус за 10 секунд, значит, стрелки до "рукопожатия" поворачиваются каждая на свой угол за 32,7272 * 10 + 3600 = 3927,272 (с) Теперь простейшая программка всего в несколько строчек рассчитает времена всех "рукопожатий" с любой желаемой точностью. Я пожелал миллисекундную точность. //-------------------------------------------------- #include <iostream> #include <iomanip> using namespace std; int main(void) { float t = 3927.272; int h, m; float s; for (int i = 0; i <= 10; i++) { h = int(i * t / 3600); m = int(i t - h 3600) / 60; s = i t - h * 3600 - m 60; cout std::setfill('0') std::setprecision(3) std::fixed; cout std::setw(2) h ':' std::setw(2) m ':' std::setw(6) s endl; } return 0; } //-------------------------------------------------- Вывод программы: 00:00:00.000 01:05:27.272 02:10:54.544 03:16:21.816 04:21:49.088 05:27:16.359 06:32:43.633 07:38:10.904 08:43:38.176 09:49:05.449 10:54:32.719 Формат очевидный: час:минута:секунда.миллисекунда Ну вот и всё, мой многолетний гештальт закрыт. Теперь я с точностью до миллисекунды знаю, когда сходятся часовая и минутная стрелки. Кстати, те часы из моего детства, вышедшие из строя от старости, мне удалось починить, и теперь они исправно тикают и демонстрируют свои "рукопожатия" на той же стене и на том же самом месте. И при желании на них даже можно взглянуть, перевернувшись вверх ногами, что, надеюсь, когда-нибудь и проделают мои дети. -- Alexander A. Vorobyov (2:5030/1103.1) shurale@shurale.net t.me/shura_le --- Нotdoged/2.13.5/Android |