Казалось бы, что может быть общего между одной из самых популярных математических теорем, Гомером Симпсоном и Дональдом Кнутом? Как и многие другие интересные идеи и задачи, их объединяет математика. Иногда даже кажется, что почти всё в этом мире сводится к математике и программированию.
Задача, о которой я хочу рассказать, совсем не сложная. Думаю, её без труда сможет решить даже начинающий программист. Но эта задача интересна и весьма необычна. Ведь не каждый день предоставляется возможность проверить вычисления героя культового мультсериала Гомера Симпсона.
Что это за теорема?
Большинство читателей, конечно же, неоднократно слышали о Великой теореме Ферма. О ней написано множество научных статей, она упоминается в книгах, рассказах, фильмах и мультсериалах. Не удивлюсь, если ей даже посвящена какая-нибудь басня.
Для тех, кто подзабыл, что это за теорема, приведу краткий экскурс в историю:
В третьем веке до нашей эры Диофант Александрийский пишет труд по арифметике, в котором предлагает читателям найти решение уравнения x2 +y2 = z2 в целых числах.
В 1637 году Пьер Ферма изучает книгу Диофанта Александрийского. Ферма без труда понимает, что у предложенного уравнения бесконечное количество решений и формулирует гораздо более интересную задачу: найти целочисленные решения для уравнения x3+ y3 = z3. Эта задача оказалась уже не такой простой, как предыдущая. Ферма смог найти только тривиальные решения, вроде 03 + 73 = 73. Это, конечно, математически верно, но совершенно неинтересно. В итоге Ферма решает, что для целых степеней p > 2 уравнение xp + yp = zp не имеет целочисленных решений. Это и есть та самая Великая теорема Ферма. Причём это была не просто гипотеза: Ферма удалось строго математически доказать это утверждение (не будем тут останавливаться на версии, что Ферма просто пошутил). Однако он не стал записывать доказательство, вместо этого он написал на полях книги Диофанта такую фразу: «Я нашёл этому поистине чудесное доказательство, но поля книги слишком узки для него». Кстати, вам это не напоминает некоторые технические задания: «Тут и так всё ясно — нечего и записывать»?
С 1637 года до нашего времени математики пытались доказать Великую теорему Ферма. Некоторым удалось найти доказательство для отдельных малых степеней (3, 5, 7 и некоторых других). Но доказать теорему полностью не удавалось никому.
В 1995 году математик Эндрю Уайлс из Принстонского университета наконец опубликовал полное доказательство теоремы. Текст доказательства занимает 130 страниц математических формул. Хотя теорема и доказана, многие математики сомневаются, что сам Ферма имел в виду именно такое громоздкое доказательство. Кроме того, Уайлс использовал множество современных математических методов, которые ещё не существовали во времена Ферма.
При чём здесь Гомер Симпсон?
В 1998 году на экраны вышла очередная серия десятого сезона «Симпсонов» — «Волшебник вечнозелёной аллеи». В ней Гомер Симпсон соревнуется в изобретательском таланте с самим Томасом Эдисоном. Как и у каждого заправского изобретателя у Гомера есть грифельная доска, на которой он пишет разные формулы и рисует чертежи будущих изобретений. В течение нескольких секунд мы видим в кадре эту доску, на которой написано равенство: 398712 + 436512 = 447212. Там есть другие надписи и рисунки, но нас сейчас интересует именно эта запись. Выглядит так, будто Гомер написал решение уравнения Великой теоремы Ферма. Но к этому мы ещё вернёмся.
Доска изобретателя Гомера — это одна из многочисленных математических шуток в «Симпсонах». В сериале они появляются постоянно: в виде особенных чисел, формул, чертежей, фраз героев, кодов и шифров. Некоторые из них видны в кадре всего на мгновение, но внимательные зрители их находят и стараются разгадать.
В таком обилии математических отсылок и аллюзий в сериале нет ничего удивительного: многие сценаристы «Симпсонов» имеют математическое образование. Например, один из сценаристов серии «Волшебник вечнозелёной аллеи» Дэвид Коэн — это математик и программист, который в какой-то момент увлёкся написанием весёлых историй для популярного сериала. Интересно, что в школе Дэвид был типичным «гиком», организатором группы программистов Glitchmaster («Мастера глюков»), которая занималась программированием. Например, они создали собственный язык программирования FLEET для разработки ускоренной графики на компьютере Apple II Plus. Затем он одновременно закончил Гарвард (получив степень бакалавра по физике) и Беркли (получив степень магистра по компьютерным наукам).
Нет ничего удивительного, что в сериале, написанном программистами, физиками и математиками, периодически появляются математические шутки и загадки. Этой теме посвящена очень интересная книга «Симпсоны и их математические секреты», написанная Саймоном Сингхом в 2016 году. Там среди прочего описана и шутка про Великую теорему Ферма.
Кстати, похожее равенство появлялось в сериале и раньше — в серии, посвящённой Хэллоуину в 1995 году. Там есть эпизод, в котором Гомер из своего привычного плоского мира попадает в трёхмерное пространство. В странном мире трёхмерных моделей вокруг Гомера летает множество неких загадочных научных объектов и формул. Одна из них выглядит так: 178212 + 184112 = 192212. Кстати, автор этого эпизода — уже знакомый нам Дэвид Коэн.
Чем особенны именно эти цифры?
Давайте разберёмся, чем же так примечательны эти равенства. Напомню, что интересующие нас серии «Симпсонов» вышли в 1995 и 1998 годах — время начала расцвета сериала. В эти же годы появились одноимённые Windows 95 и 98, но до появления первой версии Android оставалось ещё 10 лет. Да и сама компания Google была основана только осенью 1998 года. В то время у инженеров, учёных и математиков ещё были в ходу инженерные (или научные) калькуляторы, на которых можно было делать довольно сложные вычисления. Поэтому зрители проверяли равенство, написанное Гомером, скорее всего, с помощью такого калькулятора.
Я решил повторить этот эксперимент и отыскал свой старый добрый CASIO FX-911W, который верой и правдой служил мне на бесконечных лабораторных работах по физике и электротехнике, а потом и в аспирантуре. Как ни удивительно, спустя 20 лет калькулятор всё ещё прекрасно функционирует. Проверить уравнение несложно. Набираем:
(3987 [xy] 12 + 4365 [xy] 12) [xy] (1÷12) =
Получаем ответ: 4472.
Что примечательно, ответ целый, дробная часть полностью отсутствует. Всё выглядит так, как будто Гомер Симпсон успешно нашёл решение уравнения Великой теоремы Ферма в целых числах.
Аналогично можно проверить и второе равенство:
(1782 [xy] 12 + 1841 [xy] 12) [xy] (1÷12) =
Ответ: 1922.
Если у вас тоже есть инженерный калькулятор, вы можете разыграть своих друзей, интересующихся математикой. Секрет заключается в том, что числа 4472 и 1922 настолько близки к решению, что десяти разрядов калькулятора уже недостаточно, чтобы показать первый отличный от нуля разряд дробной части.
Современные компьютерные программы-калькуляторы уже считают гораздо точнее, с ними такой фокус не пройдёт. Например, калькулятор Google для первого выражения выдаст ответ 4472,00000001. Так что чуда не произошло — в математике «почти» не считается. Но на инженерном калькуляторе действительно выглядит эффектно.
Постановка задачи
В книге Саймона Сингха не только рассказывается вся эта история, но и упоминается, что Дэвид Коэн написал программу для нахождения решения уравнения, наиболее близкого к целому числу. Прочитав это, я захотел сам написать аналогичную программу, чтобы не только воспроизвести равенства Гомера Симпсона, но и найти другие варианты решения. Понятно, что никакой реальной пользы от такой программы не будет, но задач с практическим смыслом нам всем и так хватает в повседневной жизни. Иногда хочется написать что-то страшно непрактичное.
Написать такую программу — задача совсем не сложная. Её решение доступно любому начинающему программисту. Нам потребуется просто перебрать значения из определённого диапазона и найти наилучшее решение.
Сформулирую задачу. Нужно найти решение Великой теоремы Ферма в целых числах (шутка!). На самом деле нужно найти целые числа a и b и целую степень p, которые дают наиболее близкое к целому число c в выражении: ap + bp = cp.
У задачи есть важное ограничение, о котором нужно не забыть. Программа не должна выдавать тривиальные решения. Например, решение 100050 + 50050 = 100050 не подходит. Понятно, что второе слагаемое настолько меньше первого, что им вообще можно пренебречь.
Кстати, в сети пишут, что Дональд Кнут в первом издании своего «Искусства программирования» (1968 год) предложил читателям написать программу, которая доказывала бы Великую теорему Ферма. Он оценил решение этой задачи по максимуму: в 50 баллов. Также пишут, что в разделе ответов он указал, что один из читателей «нашёл потрясающее доказательство, но места для него недостаточно». Дональд Кнут тоже не прочь был пошутить.
Самый простой вариант решения
Приведу здесь самый простой вариант решения. Поскольку в «Симпсонах» в обоих равенствах используются четырёхзначные числа, попробуем решить задачу именно для них. При этом будем проверять степени от 3 до 20. Чтобы избежать тривиальных решений, ограничим значение b. Пусть оно будет отличаться от a не больше, чем на 500. Отдельно найдём решение для чисел, которые чуть больше и чуть меньше требуемого целого. Выведем на экран не только варианты решения с минимальной и максимальной дробной частью, но и те, у которых дробная часть меньше 0,0000001 или больше 0,9999999.
Вот как выглядит мой вариант программы на Delphi:
program ferma;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes, Math;
var
p, a, b: integer;
best_p_min: integer = 1;
best_p_max: integer = 1;
best_a_min: integer = 1;
best_a_max: integer = 1;
best_b_min: integer = 1;
best_b_max: integer = 1;
best_c_min: integer = 1;
best_c_max: integer = 1;
min: extended = 1;
max: extended = 0;
c, k, u: extended;
function print_result (a_res, b_res, c_res, p_res: integer; h_res: extended): string;
// Формирование строки с результатами
begin
result:=inttostr(a_res)+'^'+inttostr(p_res)+'+'+inttostr(b_res)+'^'+inttostr(p_res)+'='+inttostr(c_res)+'^'+inttostr(p_res)+' '+floattostrf(h_res,ffFixed,18,18);
end;
begin
for p:= 3 to 20 do
// Перебираем степень от 3 до 20
begin
for a:= 1000 to 9500 do
// Первое слагаемое - перебираем четырёхзначные числа
begin
for b:= a to a+500 do
// Второе слагаемое - перебираем следующие 500 чисел после первого слагаемого
begin
k:=intpower(a,p)+intpower(b,p); // Сумма a^p + b^p
c:=power(k,(1/p)); // Корень степени p из полученной суммы
u:=frac(c); // Дробная часть числа c
if (u<min) then
// Числа, которые чуть больше требуемого целого
begin
min:=u;
best_p_min:=p;
best_a_min:=a;
best_b_min:=b;
best_c_min:=trunc(c); // Целая часть числа c
end;
if (u<0.0000001) then writeln(print_result(a, b, trunc(c), p, u));
if (u>max) then
// Числа, которые чуть меньше требуемого целого
begin
max:=u;
best_p_max:=p;
best_a_max:=a;
best_b_max:=b;
best_c_max:=trunc(c)+1; // Целая часть числа c, увеличенная на 1
end;
if (u>0.9999999) then writeln(print_result(a, b, trunc(c)+1, p, u));
end;
end;
end;
// Выводим лучшие результаты
writeln('Best min result: '+print_result(best_a_min, best_b_min, best_c_min, best_p_min, min));
writeln('Best max result: '+print_result(best_a_max, best_b_max, best_c_max, best_p_max, max));
end.
Даже такой простейший вариант программы выдаст нам много чего интересного. Итак, для начала посмотрим на варианты решения с минимальной дробной частью. Решения расположены в порядке уменьшения дробной части. В таблице выделена строка с решением Гомера Симпсона.
Решение |
Остаток |
886614 + 903814 = 941214 |
0,000000079739367109 |
51713 + 52453 = 65623 |
0,000000061929320339 |
71445 + 72215 = 82515 |
0,000000047202465936 |
443314 + 451914 = 470614 |
0,000000039869683555 |
67733 + 71633 = 87863 |
0,000000034545093008 |
30973 + 35183 = 41843 |
0,000000019041251242 |
398712 + 436512 = 447212 |
0,000000007059291374 |
Похоже, в этом случае Гомер Симпсон нашёл самый подходящий ответ для четырёхзначных чисел.
Теперь посмотрим на аналогичную таблицу, содержащую варианты решения с максимальной дробной частью. Решения расположены в порядке возрастания дробной части.
Решение |
Остаток |
356412 + 368212 = 384312 |
0,999999911734451130 |
753614 + 763914 = 797414 |
0,999999926151052154 |
682511 + 688411 = 730011 |
0,999999936286894098 |
21114 + 22854 = 26194 |
0,999999939754441458 |
258219 + 304119 = 304719 |
0,999999949215854667 |
178212 + 184112 = 192112 |
0,999999955867226786 |
755520 + 762120 = 785620 |
0,999999965707043970 |
Здесь решение Гомера Симпсона только на втором месте. Похоже, Дэвид Коэн в своей программе не дошёл до степени 20. Это уже интересный результат.
Если в нашей программе увеличить максимальную степень до 30, то лучший результат в первой таблице останется неизменным, а во второй таблице появится новый максимум: 672724 + 698424 = 708424. Остаток — 0,999999982255980857. А вот увеличение максимальной степени до 50 этот результат уже не поменяет.
Для трёхзначных чисел и степеней от 3 до 20 лучшие решения будут такими:
Решение |
Остаток |
41910 + 46210 = 47710 |
0,000000873345714497 |
28010 + 30510 = 31610 |
0,999999926939411254 |
Только вот на калькуляторе они уже выглядят не так феерично: отображается дробная часть. Так что выбор четырёхзначных чисел был вполне оправдан.
В итоге нам удалось не только повторить решение Гомера Симпсона, но и найти несколько других подходящих вариантов. И один вариант оказался даже лучше, чем у Гомера.
Статья была впервые опубликована на другом ресурсе год назад — 17 декабря 2020.
Комментарии (43)
AKudinov
17.12.2021 09:11+15Мне кажется, очень опасно применять стандартную арифметику с плавающей точкой, когда мы сравниваем числа порядка 1000^12 и рассуждаем о погрешностях порядка 10^(-9). Потому и к "калькулятору Google" есть масса вопросов, и сама вычислительная задачка явно с подвохом.
Balling
19.12.2021 08:53+1Использовать надо Mathematica или Alpha (https://www.wolframalpha.com/input/?i=63976656349698612616236230953154487896987106^(1%2F12)) или https://github.com/lcn2/calc с бесконечной точностью (проверенно!).
valis
17.12.2021 11:10+2Круто. Я замечал пару посхалок в сериале, но про существовании целой системы и даже книги не знал. Уже купил буду читать
DanilinS
17.12.2021 12:27А откуда берется дробная часть при возведении в степень? Если брать любое цельное число умножить на себя - будет всегда цельное число. Без дробной части. Или это косяки представления числа в двоичной системе?
Cerberuser
17.12.2021 12:33+4Так степень-то на последнем шаге равна 1/p. При возведении в дробную степень дробная часть, разумеется, появится.
DanilinS
17.12.2021 12:40Э... не понял. Разве a^12 не равна a*a*a*a*a*a*a*a*a*a*a*a ?! Где там появляется дробная часть?
MeOwn
17.12.2021 12:56+3Чтобы сравнить выражения, от левой части x^p + y^p потом берётся корень степени p. Ну, или возводится в степень 1/p, если переформулировать
DanilinS
17.12.2021 13:02+2А зачем нам корень извлекать? Для сравнения правой и левой части это совсем лишнее. Считаем правую и левую часть отдельно. Сравниваем.
GarretThief
17.12.2021 13:04+1В этом и суть статьи, что математика калькуляторов ломается о реальность флоатов. А в симпсонах просто воспользовались этим для дополнительной шутки.
Gummilion
17.12.2021 14:13+4Просто если от левой части вычесть правую, сразу виден подвох: получается 1,211864070e33 - что называется, даже не в одной Галактике. Поэтому извлекаем корень, чтобы было незаметно.
Metotron0
17.12.2021 18:03+2Чтобы правую часть не перебирать, а посчитать математически.
2y = x + 1; x = 5
Можно перебирать все y и сравнивать части уравнения, а можно просто x + 1 поделить пополам. Нет же вопроса, зачем его делить пополам?
salnicoff
17.12.2021 19:34+1Потому что калькулятор не умеет умножать. Он все через логарифмы и экспоненты считает, а там свои погрешности. Потому, собственно, и появляются такие приколы.
Daddy_Cool
17.12.2021 12:47+11Вау! Хабр — торт! Мне как настоящему ферматисту (в 12 лет) очень понравилось!
Захотелось проверить в Maple.
A=3987^12=16134474609751291283496491970515151715346481
B=4365^12=47842181739947321332739738982639336181640625
C=4472^12=63976656348486725806862358322168575784124416
A+B=63976656349698612616236230953154487896987106
Ну типа да — не сходится.
А теперь — магия. Извлекаем корень 12-й степени из суммы A+B
evalf((A+B)^(1/12));
И получаем… 4472.000000Balling
19.12.2021 08:58+1https://www.wolframalpha.com/input/?i=63976656349698612616236230953154487896987106^(1%2F12)
Так что все правильно. Не надо унижать GMP!
Там 8 нолей после запятой.
4472.00000000705929073821352924144940938473689768243066193961642581181025581885700714287170250554382069429582978299441080874096124021069957716998872663907962296431554357370519777805996171723726873723895550703256163015599978925231864156945746330729296709617573546234696486722883526954706549688...
DimaVadovov
17.12.2021 12:53+6Забавно, что Ферма усложнил задачу, нашел одну схему решения с 0 и такой: "Давайте посмотрим, что остальные придумают"
Kasheftin
17.12.2021 12:59+3"Ферма удалось строго математически доказать это утверждение (не будем тут останавливаться на версии, что Ферма просто пошутил)" - На лекциях по истории математики нам с абсолютной уверенностью утверждали, что Ферма ошибся, и что в то время доказать эту теорему было невозможно.
MarazmDed
17.12.2021 13:25+3На лекциях по истории математики нам с абсолютной уверенностью утверждали, что Ферма ошибся, и что в то время доказать эту теорему было невозможно.
В чем разница с версией, чтот у него было доказательство? Ни то, ни другое не доказано.
В пользу версии, что Ферма ошибся говорят следующие факты:
1) Изящное и простое доказательство до сих пор не найдено
2) Изучению проблемы посвящено 300 с лишним лет. За это время накоплен большой объем знаний о проблеме, плюс наработаны новые мат. методы. Т.е. вариант "не там ищете" - маловероятен.
3) Строгое доказательство получено, но его сложность потрясает воображение.
Vitan1
18.12.2021 06:31+2Читал также, что неоднократно предлагались ошибочные доказательства, ошибочность которых была далеко не очевидной. Это говорит в пользу версии, что Ферма добросовестно заблуждался, думая что нашел решение. Не исключено даже, что он сам это позднее понял и поэтому "доказательство" не опубликовал, но сделанная ранее запись сохранилась.
Balling
19.12.2021 09:15+1На самом деле теорема Ферма это всего лишь частный случай теоремы о модулярности.
Balling
19.12.2021 09:14+1Сложность вполне нормальная. В ключевой части доказывается модулярная теорема (в то время гипотеза Таниямы — Шимуры — Вейля) для случая семистойких эллиптических кривых. И поэтому в 1) вы не правы. Из всей модулярной теоремы, которая была доказана немного позже, напрямую следует теорема Ферма.
oleg1977
19.12.2021 15:58+1Есть изящное и простое (понятное даже мне) доказательство из ABC гипотезы: https://youtu.be/RE5GLBex3zo
karachun92
17.12.2021 13:06+23Во втором "Уравнении Гомера Симпсона" сразу видно что числа не равны.
1782^12 + 1841^12 = 1922^12
1922^12 четное а (1782^12 + 1841^12) нечетное.
Dvlbug
17.12.2021 17:57Это сразу видно человеку, но:
(с hrwiki.ru) Шутка в том, что корень двенадцатой степени из суммы действительно равен 1922 из-за ошибок округления при вводе в большинство портативных калькуляторов
DrGluck07
17.12.2021 13:54+5Если меня не подводит склероз, то Гомер такой не очень умный потому, что у него в носу вставлен карандаш. Когда карандаш достали, Гомер стал гением, но при этом очень несчастным, поэтому засунул карандаш обратно.
lzrnk
17.12.2021 16:04+2Если посмотреть на ряд чисел 0, 1, 8, 27, 64, 125 (кубы целых чисел), то можно заметить что сумма любых двух соседних чисел (это максимум) всегда меньше следующего числа. То есть какие два куба не складывай до следующего не достать. 4 и последующие степени тем более.
631052
17.12.2021 16:34+1как уже было замечено, у трехмерного Симпсона "четное + нечетное = четное", что не бывает.
но что такое там справа, не совсем попавшее в кадр? уж не утверждение ли о равенстве классов P и NP? одна из Задач Тысячеления так-то
да вот еще, глаз зацепился за тезис "в математике "почти" не считается" - в данном случае да, конечно не считается. но в общем и целом - еще как. "почти всюду", вот это всё. да чорт, в математике есть даже "большая половина".
631052
17.12.2021 16:40Александр, технический вопрос не по теме поста:
указано, что статья впервые опубликована в другом месте такого-то числа - это обязательное требование об указании данной информации?
gameplayer55055
17.12.2021 21:55Мистер https://0.30000000000000004.com/ не даст решить хорошо задачу на компе. Или эмулировать десятитный процессор или считать в уме
Goodwinnew
18.12.2021 08:45+1если мы считаем в целых числах (что бы без дробей после корня) = то в сравнеии будут отклонения в целых числах.
но у нас 64 разряда- это всего 10 в 19 степени.
для больших степеней может не хватить (и не хватит). нужно подключать специальные библиотеки, что бы можно было использовать несколько ячеек памяти под число. тогда можно проверять до упора - насколько памяти хватит :)
v1000
Круто! Особенно прикол с калькулятором. Даже показалось, что это реальная обложка книги - калькулятор там очень в тему.