Коли це стало кодовим гольфом? Я думав, що це виклик коду - придумати найкращий алгоритм!
код-гольф
APL, 33 символи
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}
Це простий лінійний пошук, починаючи з C = 1 + 10 -6 і збільшуючи його на 10 -6 до
log C log C log C ⋯ A ≤ 1,
де функція log C застосовується рекурсивно B разів.
Приклади
4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113
Цей код дуже повільний, але для невеликих баз, таких як 2 або 3, він завершується за кілька секунд. Дивіться нижче для кращої речі.
виклик коду
APL, логарифмічна складність
Фактично лінійна складність у кореневому порядку, логарифмічна за розміром результату та точністю:
час = O (B × log (C) + B × log (D))
де B - кореневий порядок, C - база тетрації, про яку запитують, і D - число розпитаних точностей. Ця складність є моїм інтуїтивним розумінням, я не представив формального доказу.
Цей алгоритм не вимагає великих цілих чисел, він використовує лише функцію журналу для регулярних чисел з плаваючою комою, тому він досить ефективний для дуже великих чисел, аж до межі реалізації плаваючої точки (або подвійна точність, або довільні великі числа FP на Реалізації APL, які їх пропонують.)
Точність результату можна контролювати, встановивши ⎕CT
(порівняльну толерантність) до бажаної допустимої помилки (у моїй системі вона за замовчуванням до 1e¯14, приблизно 14 десяткових цифр)
sroot←{ ⍝ Compute the ⍺-th order super-root of ⍵:
n←⍺ ⋄ r←⍵ ⍝ n is the order, r is the result of the tetration.
u←{ ⍝ Compute u, the upper bound, a base ≥ the expected result:
1≥⍵⍟⍣n⊢r:⍵ ⍝ apply ⍵⍟ (log base ⍵) n times; if ≤1 then upper bound found
∇2×⍵ ⍝ otherwise double the base and recurse
}2 ⍝ start the search with ⍵=2 as a first guess.
(u÷2){ ⍝ Perform a binary search (bisection) to refine the base:
b←(⍺+⍵)÷2 ⍝ b is the middle point between ⍺ and ⍵
t←b⍟⍣n⊢r ⍝ t is the result of applying b⍟ n times, starting with r;
t=1:b ⍝ if t=1 (under ⎕CT), then b is the super-root wanted;
t<1:⍺∇b ⍝ if t<1, recurse between ⍺ and b
b∇⍵ ⍝ otherwise (t>1) returse between b and ⍵
}u ⍝ begin the search between u as found earlier and its half.
}
Я не впевнений, чи 1≥⍵⍟⍣n
може вищезгадана помилка з помилкою домену (тому що журнал негативного аргументу може або вийти з ладу негайно, або дати складний результат, який би не був у домені ≥
), але мені не вдалося знайти випадок, який не вдається.
Приклади
4 sroot 65536
1.9999999999999964
4 sroot 65537
2.000000185530773
3 sroot 7625597484987
3
3 sroot 7625597400000
2.999999999843567
3 sroot 7625597500000
3.000000000027626
"3" виходить як точне значення, оскільки воно буває одним із значень, безпосередньо потрапляє в бінарний пошук (починаючи з 2, подвоєного до 4, бісектного до 3). У загальному випадку цього не відбувається, тому результат буде наближатись до значення кореня з помилкою ⎕CT (точніше, логарифмічний тест кожної бази-кандидата виконується з толерантністю ⎕CT.)