Pull to refresh
112
167.1
Сергей Ю. Каменев @inetstar

Алгоритмист. Автор. Поставщик SSD, RAID, серверов.

Send message

Похоже ваш код так и делает, как я предложил. Извините, торопился, понял неправильно.

Да, типа как таблицу квадратов: n^2, n^4, n^8, n^16, n^32. В общем случае n^(2^i). Но в принципе можно, наверное, извратиться, чтобы и без таблицы вовсе. Или можно таблицу сделать в стеке и рекурсией вынимать из неё значения.

Так меньше всего действий. Всё через умножение.

Вопрос. Если бы у вас стояла задача просто сделать телеграмм мини апп, то какой бы стэк вы выбрали?

Представьте у клиента нет никаких мобильных приложений. Причём, желательно, чтобы бэкэнд можно было подключить на любом языке, не только на node.js.

В принципе для итеративного возведения в целую степень можно было написать функцию, которая возводит в квадраты. Потребовалось бы сильно меньше итераций.

n^2 - (n^2)^2 - .... - n^4096 (12 шагов для получения n^4096)
*(n^2048)*(n^1024)*(n^512)*(n^256)*(n^64) плюс ещё 5 умножений на известные числа

Итого 17 шагов.

Вставил инфу о BSD версии bc в статью и твоём тестировании.

Да, из математических программ. Я использую PARI для математического моделирования, модульной арифметики и криптографических задач.

До этого пользовался Maxima, а ещё до этого Derive. Последняя впечатлила ещё тогда, когда работала под DOS.

Mathematica - совсем чуть-чуть.

Системы компьютерной алгебры меня очаровали ещё давно. Дают чувство волшебства, когда сложные задачи могут символьно решать. Или численно с невообразимой точностью.

PARI ещё умеет мультипроцессорность использовать очень просто. Отдельную статью напишу про это.

Спасибо за сравнение и комментарии. Кстати, благодаря нашим тестам я нашёл небольшой баг в PARI и отправил вчера баг-репорт.

Да, чтобы задать вещественную степеньв Pari нужно к целому числу, например, добавить 0.0. Чтобы произошло преобразование типа к вещественному.

Попробуйсте посмотреть до какого порядка нормально работают эти утилиты и за какое время, пожалуйста. Я вставлю информацию в статью.

Вы что-то путаете. Вот официальное место для скачки. Там последняя версия 1.07.

The fourth is an independent implementation by Gavin Howard[1] that is included in Android (operating system),[2][3] FreeBSD as of 13.3-RELEASE,[4][5][6] and macOS as of 13.0.[7][8][9]

В линуксе эта версия не используется.

Итак, результат любого деления/умножения/степени c участием обычного float имеет тип обычного float.

1.0 / SetPrecision[n, 24500] // Precision
15.9546


SetPrecision[Pi, 24500]^ 3.0 // Precision
MachinePrecision


N - не гарантированно повышает точность. В отличие от SetPrecision.

N[1.0, 24500] // Precision
MachinePrecision

SetPrecision[1.0, 24500] // Precision
24500

Если в середине числа много нулей, а в конце значащий бит, то Математика поднимает точность в 2 раза

1 + 1/SetPrecision[n, 24500] // Precision
48943

Иногда при экспоненциации Математика теряет точность (если показатель степени вещественен, но не всегда).

(1 + 1/SetPrecision[n, 24500])^SetPrecision[n, 24500] // Precision
72.9546

SetPrecision[Pi, 24500]^ SetPrecision[Pi, 24500] // Precision
24499.2

Вот сколько неочевидных моментов....

Не уверен, что это хорошо, что Математика сама решает какую точность выдать.

(N[1 + 1/10^24443, 24500])^N[10^24443, 24500]2.71828182845904523536028747135266249775724709369995957497

(N[1 + 1/10^24443, 24500])^N[10^24443, 24500] // Precision
57


Когда я сделал это в PARI она честно выплюнула огромную простыню.

default(realprecision, 24500);
(1 + 1.0/10^24443)^(10^24443)
2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059.......................


Потом я сделал в Математике:
(N[1 + 1/10^24443, 50000])^N[10^24443, 50000]

Получил простыню и проверил все знаки, что посчитала PARI - знаки верные.
Вывод: Математика иногда жульничает и не выдаёт результат с нужной точностью.
То, что на встроенный показатель точности полагаться нельзя - это плохо.

Потом в PARI вычислил следующее:
(1.0 + 1.0/10^24444)^(10.0^24444)
2.7182818284590452353602874713526624977572470936999595749669675985385547268541


Получил в ответ короткое число, как видишь.

Вывод: механизм возведения в степень у обоих программ схож. Если показатель степени вещественное число, то считает урезанно. Если показатель степени целый, то старается считать как можно точнее. C целым показателем показателем степени Математика страшно замедляется, но быстрее PARI в 2.5 раза, правда чисел выводит всё-равно раза в 2 меньше.

(N[1 + 1/10^24443, 24500])^(10^24443) // Timing
{3.70777, 2.71828182845904523536028747135266249775724709369995957497}


С целым показателем степени Математика работает существенно дольше. Уже всего в 3 раза быстрее, чем PARI. Но, чисел выдала с целым показателем значительно меньше, чем PARI.

Чтобы заставить Математику выдать 24500 цифр я использовал выражение:

(N[1 + 1/10^24443, 50000])^(10^24443) // Timing

И на моём ноуте оно выполнялось 29 секунд. Против 10 секунд у PARI.

А вот в вещественной степени Математика оказалась в 2.5 раза быстрее. Но опять с потерей точности.

PARI - 5 микросекунд
(1.0 + 1/10^24443)^(10^24443+0.0)
2.7182818284590452353602874713526624977572470936999595749669676260605536564921


Математика
(N[1 + 1/10^24443, 24500])^N[10^24443, 24500] // Timing
{0.002106, 2.71828182845904523536028747135266249775724709369995957497}


Как выяснилось есть много подводных камней. И функции возведения в степень, если экспонента вещественная сделаны с существенной потерей точности в обоих программах.

Видимо, Математика как-то заточена чтобы немножно хитрить на больших числах, Пари пытается считать точно и вылетает по памяти на очень больших числах.

Пока что я вижу, что при одинаковой выходной точности PARI работает не хуже, а временами лучше (на целочисленных степенях).

А какая будет логика суммирования в double double? Положительные значения в одну переменную, а отрицательные в другую? Почему это даст прирост точности?

Есть какой-то подвох. Это выражение выдаёт результат примерно в 500 цифр
(N[1 + 1/10^24444, 25000])^N[10^24444, 25000] // Timing

А вот это в несколько тысяч. Это странно
(N[1 + 1/10^4000, 25000])^N[10^4000, 25000] // Timing

Это странно. Если поднять точность до 50000, то получается простыня...

11-я математика с указанием избыточной точности на ноуте тоже посчитала c 10^1000000000. Видимо, дело в том, что когда мы используем целые Mathematica преобразует в дробь, а дробь уже пытается перевести в целое.

А с избыточной точностью числа сразу получаются вещественными.

Но проверил ниже и не подтвердилось...

(1 + N[1/10^2000, 1000])^N[10^2000, 1000]
Overflow[]
Это выражение у меня вызывает Overflow, хотя каждый компонент в отдельности это Real

(N[1, 1000] + N[1/10^2000, 1000])^N[10^2000, 1000]
Overflow[]

(1.0 + N[1/10^2000, 1000])^N[10^2000, 1000]
1.0

Похоже, что overflow означает, что ему не хватает точности. что теряет разряды. Но ведь это не проблема при апроксимации?

(N[1 + 1/10^2000, 1000])^N[10^2000, 1000]

Тоже overflow

Фигня вышла такая же, как и у меня. Тоже ноль. Кстати, а зачем ты (можно так?) указываешь точность в миллиардах знаков? Для моего теста нужна всего лишь 1000.

1
23 ...

Information

Rating
24-th
Location
Москва, Москва и Московская обл., Россия
Works in
Date of birth
Registered
Activity