Известная апория Зеннона[0] о том, что Ахиллес не сможет догнать черепаху, потому что за время, когда он достигнет её исходного положения, она успеет отползти дальше, после чего всё повторится — это очередная логическая задача, которая до сих пор вводит в заблуждение многих людей, но оказывающаяся неприлично простой, если для её рассмотрения использовать язык программирования[1].
Если бы нас интересовало время, за которое Ахиллес должен догнать черепаху, то мы бы просто записали так:
MODULE Overtaking;
PROCEDURE Time*(vt, va, d0: REAL) : REAL;
RETURN
d0 / (va - vt)
END Time;
END Overtaking.
Этим вопрос был бы исчерпан, но если следовать размышлениям Зеннона, то расчёт времени следует разбить на этапы, в которых Ахиллес оказывается на месте, которое занимала бы черепаха, если бы не двигалась. Тогда код усложнится[2] до следующего.
MODULE Zeno;
PROCEDURE Run*(vt (* скорость черепахи *),
va (* скорость Ахиллеса *),
d0 (* расстояние между ними *): REAL
) : REAL;
VAR d1, t0, t: REAL;
BEGIN
t := 0.0;
REPEAT
(* время достижения Ахиллесом исходного места черепахи *)
t0 := d0 / va;
(* расстояние, на которое удалится черепаха за это время *)
d1 := t0 * vt;
t := t + t0;
(* на следующем шаге рассмотрения смещение черепахи становится
исходным расстоянием между черепахой и Ахиллесом *)
d0 := d1
UNTIL d0 = 0.0
RETURN
t
END Run;
END Zeno.
Такая функция несмотря на свою неэффективность вполне вычислима на компьютере, поскольку дроби, используемые в компьютерных вычислениях, имеют ограниченную точность, из-за чего вычисляемое расстояние между бегунами неизбежно достигнет 0 даже в таком рассмотрении.
Для соответствия кода размышлениям Зеннона мы не будем использовать дроби неограниченной точности, а произведём тождественную замену, позволяющую избавиться от зависимости от ограничения точности, а заодно позволяющую лучше понять суть подхода Зеннона. Можно заметить, что в нём нас интересует не столько расстояние, сколько соотношение конечного расстояния к начальному в каждом шаге рассмотрения. Заменим условие завершения с d0 = 0.0 на d1 / d0 = 0.0
REPEAT
t0 := d0 / va;
d1 := t0 * vt;
k := d1 / d0;
t := t + t0;
d0 := d1
UNTIL k = 0.0
Устраним вычисление t0, подставив его в вычисление d1 напрямую без промежуточной переменной.
REPEAT
d1 := d0 / va * vt;
k := d1 / d0;
d0 := d1
UNTIL k = 0.0;
Подставим вычисление d1 в вычисление k
REPEAT
k := d0 / va * vt / d0
UNTIL k = 0.0;
Упростим вычисление k, сократив d0 и перенеся vt
REPEAT
k := vt / va
UNTIL k = 0.0;
Поскольку скорости не меняются, то и соотношение между ними тоже, поэтому вычисление соотношений расстояний можно вынести из повторения.
k := vt / va;
REPEAT
UNTIL k = 0.0;
Это и есть суть апории про Ахиллеса и черепаху, если очистить её от словесной шелухи, создающей иллюзию того, что что-то происходит. На самом деле она сводится к пустому повторению проверки ложного условия завершения повторения. Вычислительный Ахиллес никогда не догонит вычислительную черепаху, потому что вычисление составлено таким образом, чтобы этого не произошло. Только это не вывод, а закладываемое свойство. В этом и заключается подмена понятий в апории Зеннона, ведь в ней заложенное свойство подаётся как вывод.
Второй логической ошибкой относительно апории является подразумеваемая правомерность переноса псевдовывода о невозможности догнать черепаху в специально составленном для этого вычислении на действительность, где подтвердилось бы обратное, из чего и следует мнимое противоречие.
Нет никакого противоречия в том, что зацикленный код оказывается не способным завершиться, выполнив исходную задачу. Но если программисту понятно, что зацикленное вычисление — это ошибка, которую нужно исправить, и что зацикленность не означает ничего, кроме этого, то для не некоторых недобросовестных философов зацикленность мысленного опыта — это повод для далеко идущих выводов о свойствах пространства и времени. И никакое правильное объяснение не сможет этого исправить.
[0] Апория Зеннона на wikipedia.
[1] Смотрите язык программирования для людей как средство понимания.
[2] Само по себе усложнение кода являетя тревожным признаком, ведь в сложном коде проще спрятать ошибку, чем в простом.

Комментариев нет:
Отправить комментарий