Python, “численный” j-инвариант и десятичные цифры

На скриншоте ниже – результат работы нехитрой программы на языке Python, которая вычисляет в точке x == i (мнимая единица) значение функции, известной как j-инвариант – j(x).
Screen of Numbers
j(x) – это модулярная функция, которая важна, например, в теории эллиптических кривых, но в настоящей заметке теоретические детали не играют существенной роли. Значение j(x) для мнимой единицы – это целое число 1728 (в каком-то смысле, по определению). А 1728 == 12^3, что тоже не является простым совпадением, так как 12 == 2^2 * 3. Можно j(x) записать в виде бесконечной суммы (разложение Фурье или q-expansion, если хотите, где q == exp(2*π*i*x)), что и используется в программе: j(x) == q^(-1) + 744*q^(0) + 196884*q^1 + 21493760*q^2 + 864299970*q^3 +… Коэффициенты – целые числа.

Поскольку модулярные формы имеют большое значение в арифметике, коэффициенты из разложения j-инварианта проявляются в математике довольно неожиданным образом, порождая даже отдельные направления (как в случае “Чудовищной бурды” – Monstrous Moonshine, самогон, который в русскоязычной “Википедии” едва не превратился в “Монструозный отблеск”). Но это тема для другой записки, более подробной. Здесь же отметим, что так как коэффициенты – целые числа, можно взять их побольше (например, 42) и посчитать значение j(x) “численными методами”, проверив, сойдётся ли, и насколько быстро, результат. Понятно, что если в выражение для q (см. выше) подставить x == i, вместо i*i получится -1, что и делает каждый очередной элемент суммы всё меньше и меньше, несмотря на увеличивающиеся коэффициенты.

Однако здесь есть хитрости. Если использовать обычные настройки Python, то точности для вычислений не хватает, результат не сходится. Если взять math.exp() и math.pi, точность по умолчанию, получаем 1728.000000000000014825929946, причём ещё на 13 шаге суммирования – не очень-то хороший результат: больше чем 1728. Увеличение точности само по себе тут не помогает, нужно использовать модуль decimal и ввести достаточно длинные значения для π и e, заменив math.exp() и math.pi на Decimal(E**(Decimal(-2)*Pi))**n, где E и Pi – значения со многими знаками после запятой. Точность в decimal устанавливается при помощи getcontext().prec. Результат со скриншота получен для prec = 81 в Python 3.5. Всё это хорошо иллюстрирует, что компьютеры не считают в действительных числах.

Исходный код (проверьте, что символы табуляции не были “съедены” так же, как и некоторые цифры десятичного разложения):

from decimal import Decimal, getcontext
getcontext().prec = 81
Pi =	Decimal('3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982')
E =	Decimal('2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427')
M = [
1, 744, 196884, 21493760, 864299970, 20245856256, 333202640600,
4252023300096, 44656994071935, 401490886656000, 3176440229784420,
22567393309593600, 146211911499519294, 874313719685775360,
4872010111798142520, 25497827389410525184, 126142916465781843075,
593121772421445058560, 2662842413150775245160, 11459912788444786513920,
47438786801234168813250, 189449976248893390028800, 731811377318137519245696,
2740630712513624654929920, 9971041659937182693533820, 35307453186561427099877376,
121883284330422510433351500, 410789960190307909157638144, 1353563541518646878675077500,
4365689224858876634610401280, 13798375834642999925542288376, 42780782244213262567058227200,
130233693825770295128044873221, 389608006170995911894300098560, 1146329398900810637779611090240,
3319627709139267167263679606784, 9468166135702260431646263438600, 26614365825753796268872151875584,
73773169969725069760801792854360, 201768789947228738648580043776000, 544763881751616630123165410477688,
1452689254439362169794355429376000
]
j = Decimal(0)
n = -1
for c in M:
	j = j + Decimal(c) * Decimal(E**(Decimal(-2)*Pi))**n
	print("j = ", j)
	n = n + 1
print("j^(1./3) =", float(j)**(1./3))

Адрес записки: https://dxdt.ru/2023/06/06/10255/

Похожие записки:



Далее - мнения и дискуссии

(Сообщения ниже добавляются читателями сайта, через форму, расположенную в конце страницы.)

Написать комментарий

Ваш комментарий:

Введите ключевое слово "83SWZ" латиницей СПРАВА НАЛЕВО (<--) без кавычек: (это необходимо для защиты от спама).

Если видите "капчу", то решите её. Это необходимо для отправки комментария ("капча" не применяется для зарегистрированных пользователей). Обычно, комментарии поступают на премодерацию, которая нередко занимает продолжительное время.