Khi nào thì điều này trở thành một mã golf? Tôi nghĩ rằng đó là một thách thức mã để đưa ra thuật toán tốt nhất!
mã golf
APL, 33 ký tự
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}
Đây là một tìm kiếm tuyến tính đơn giản, bắt đầu từ C = 1 + 10 -6 và tăng nó lên 10 -6 cho đến khi
log C log C log C ⋯ A 1
trong đó hàm log C được áp dụng đệ quy B lần.
Ví dụ
4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113
Mã này rất chậm, nhưng đối với các cơ sở nhỏ như 2 hoặc 3, nó sẽ hoàn thành trong vài giây. Xem dưới đây cho một điều tốt hơn.
thử thách mã
APL, độ phức tạp logarit
Thực tế độ phức tạp tuyến tính trên thứ tự gốc, logarit về kích thước và độ chính xác của kết quả:
thời gian = O (nhật ký B × (C) + B × nhật ký (D))
Trong đó B là thứ tự gốc, C là cơ sở tetration được yêu cầu và D là số chữ số chính xác được yêu cầu. Sự phức tạp này là sự hiểu biết trực quan của tôi, tôi đã không đưa ra một bằng chứng chính thức.
Thuật toán này không yêu cầu số nguyên lớn, nó chỉ sử dụng hàm log trên các số dấu phẩy động thông thường, do đó nó khá hiệu quả với các số rất lớn, cho đến giới hạn của việc thực hiện dấu phẩy động (chính xác gấp đôi hoặc số FP lớn tùy ý trên Triển khai APL cung cấp cho họ.)
Độ chính xác của kết quả có thể được kiểm soát bằng cách đặt ⎕CT
(dung sai so sánh) thành lỗi chấp nhận được mong muốn (trên hệ thống của tôi, nó mặc định là 1e¯14, khoảng 14 chữ số thập phân)
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.
}
Tôi không chắc liệu 1≥⍵⍟⍣n
ở trên có thể thất bại với Lỗi miền hay không (vì nhật ký của đối số phủ định có thể thất bại ngay lập tức hoặc đưa ra một kết quả phức tạp, không thuộc miền ≥
) nhưng tôi không thể tìm thấy một trường hợp thất bại
Ví dụ
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' xuất hiện dưới dạng một giá trị chính xác bởi vì nó là một trong những giá trị được tìm kiếm trực tiếp bởi tìm kiếm nhị phân (bắt đầu từ 2, nhân đôi thành 4, chia thành 3). Trong trường hợp chung không xảy ra, do đó, kết quả sẽ xấp xỉ giá trị gốc với lỗi ⎕CT (chính xác hơn là kiểm tra logarit của mọi cơ sở ứng cử viên được thực hiện với dung sai ⎕CT.)