Kapan ini menjadi kode golf? Saya pikir itu adalah tantangan kode untuk menghasilkan algoritma terbaik!
kode-golf
APL, 33 karakter
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}
Ini adalah pencarian linear sederhana, mulai dari C = 1 + 10 -6 dan menambahnya dengan 10 -6 hingga
log C log C log C ⋯ A ≤ 1 di
mana fungsi log C diterapkan secara berulang B kali.
Contohnya
4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113
Kode ini sangat lambat, tetapi untuk basis kecil seperti 2 atau 3 selesai dalam beberapa detik. Lihat di bawah untuk hal yang lebih baik.
tantangan kode
APL, kompleksitas logaritmik
Sebenarnya kompleksitas linear pada urutan root, logaritmik pada ukuran dan presisi hasil:
waktu = O (B × log (C) + B × log (D))
di mana B adalah urutan root, C adalah basis tetrasi yang diminta, dan D adalah jumlah digit presisi yang diminta. Kompleksitas ini adalah pemahaman intuitif saya, saya belum menghasilkan bukti formal.
Algoritma ini tidak memerlukan bilangan bulat besar, hanya menggunakan fungsi log pada angka floating point reguler, oleh karena itu cukup efisien pada angka yang sangat besar, hingga batas implementasi floating point (baik presisi ganda, atau angka FP besar sembarang pada Implementasi APL yang menawarkannya.)
Ketepatan hasil dapat dikontrol dengan menetapkan ⎕CT
(toleransi perbandingan) untuk kesalahan yang dapat diterima yang diinginkan (pada sistem saya itu default ke 1e14, kira-kira 14 digit desimal)
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.
}
Saya tidak yakin apakah di 1≥⍵⍟⍣n
atas dapat gagal dengan Kesalahan Domain (karena log argumen negatif dapat langsung gagal, atau memberikan hasil yang kompleks, yang tidak akan ada dalam domain ≥
) tetapi saya belum dapat menemukan sebuah kasus yang gagal.
Contohnya
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' keluar sebagai nilai yang tepat karena kebetulan merupakan salah satu nilai yang langsung terkena oleh pencarian biner (mulai dari 2, dua kali lipat menjadi 4, dua bagian ke 3). Dalam kasus umum yang tidak terjadi, sehingga hasilnya akan mendekati nilai akar dengan kesalahan ⎕CT (lebih tepatnya, uji logaritmik setiap basis kandidat dilakukan dengan toleransi ⎕CT.)