Wann wurde dies ein Code Golf? Ich dachte, es wäre eine Code-Herausforderung, den besten Algorithmus zu finden!
Code-Golf
APL, 33 Zeichen
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}
Dies ist eine einfache lineare Suche, die von C = 1 + 10 -6 ausgeht und um 10 -6 erhöht wird, bis
log C log C log C ⋯ A ≤ 1,
wobei die log C- Funktion B-mal rekursiv angewendet wird.
Beispiele
4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113
Dieser Code ist sehr langsam, aber für kleine Basen wie 2 oder 3 ist er in wenigen Sekunden fertig. Siehe unten für eine bessere Sache.
Code-Herausforderung
APL, logarithmische Komplexität
Tatsächlich lineare Komplexität in der Stammreihenfolge, logarithmisch in Bezug auf Ergebnisgröße und Genauigkeit:
Zeit = O (B × log (C) + B × log (D))
Dabei ist B die Grundreihenfolge, C die angeforderte Tetrationsbasis und D die Anzahl der angeforderten Genauigkeitsziffern. Diese Komplexität ist mein intuitives Verständnis, ich habe keinen formalen Beweis erbracht.
Dieser Algorithmus erfordert keine großen Ganzzahlen, sondern verwendet die Protokollfunktion nur für reguläre Gleitkommazahlen. Daher ist er für sehr große Zahlen bis zur Grenze der Gleitkommaimplementierung (entweder doppelte Genauigkeit oder beliebig große FP-Zahlen auf der.) Sehr effizient APL-Implementierungen, die sie anbieten.)
Die Genauigkeit des Ergebnisses kann durch Einstellen ⎕CT(Vergleichstoleranz) auf den gewünschten akzeptablen Fehler gesteuert werden (auf meinem System ist der Standardwert 1e ¯ 14, ungefähr 14 Dezimalstellen).
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.
}
Ich bin nicht sicher, ob 1≥⍵⍟⍣noben ein Domänenfehler fehlschlagen könnte (da das Protokoll eines negativen Arguments entweder sofort fehlschlagen oder ein komplexes Ergebnis liefern könnte, das nicht in der Domäne von liegt ≥), aber ich konnte es nicht finden ein Fall, der fehlschlägt.
Beispiele
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' wird als exakter Wert ausgegeben, da es sich zufällig um einen der Werte handelt, die direkt von der binären Suche getroffen werden (beginnend mit 2, verdoppelt auf 4, halbiert auf 3). In dem allgemeinen Fall, in dem dies nicht der Fall ist, nähert sich das Ergebnis dem Wurzelwert mit einem ⎕CT-Fehler an (genauer gesagt, der logarithmische Test jeder Kandidatenbasis wird mit ⎕CT-Toleranz durchgeführt.)