When did this become a code golf? I thought it was a code challenge to come up with the best algorithm!
code-golf
APL, 33 chars
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}
This is a simple linear search, starting from C = 1 + 10-6 and incrementing it by 10-6 until
logC logC logC ⋯ A ≤ 1
where the logC function is applied recursively B times.
Examples
4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113
This code is very slow, but for small bases such as 2 or 3 it completes in a few seconds. See below for a better thing.
code-challenge
APL, logarithmic complexity
Actually linear complexity on the root order, logarithmic on the result size and precision:
time = O(B × log(C) + B × log(D))
where B is the root order, C is the tetration base being asked for, and D is the number of digits of precision asked. This complexity is my intuitive understanding, I have not produced a formal proof.
This algorithm does not require big integers, it only uses the log function on regular floating point numbers, therefore it's quite efficient on very large numbers, up to the limit of the floating point implementation (either double precision, or arbitrary large FP numbers on the APL implementations that offer them.)
The precision of the result can be controlled by setting ⎕CT
(comparison tolerance) to the desired acceptable error (on my system it defaults to 1e¯14, roughly 14 decimal digits)
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.
}
I'm not sure whether 1≥⍵⍟⍣n
above could fail with a Domain Error (because the log of a negative argument could either fail immediately, or give a complex result, which would not be in the domain of ≥
) but I haven't been able to find a case that fails.
Examples
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' comes out as an exact value because it happens to be one of the values directly hit by the binary search (starting from 2, doubled to 4, bisect to 3). In the general case that does not happen, so the result will approximate the root value with a ⎕CT error (more precisely, the logarithmic test of every candidate base is performed with ⎕CT tolerance.)