เมื่อไหร่ที่สิ่งนี้กลายเป็นกอล์ฟรหัส? ฉันคิดว่ามันเป็นความท้าทายของรหัสที่จะเกิดขึ้นกับอัลกอริทึมที่ดีที่สุด!
รหัสกอล์ฟ
APL, 33 ตัวอักษร
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}
นี่คือการค้นหาเชิงเส้นอย่างง่ายเริ่มต้นจาก C = 1 + 10 -6และเพิ่มขึ้นทีละ 10 -6จนกระทั่ง
ล็อกล็อกCล็อกCล็อกC ⋯ A ≤ 1
ที่ฟังก์ชันบันทึก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 คือจำนวนตัวเลขของความแม่นยำที่ถาม ความซับซ้อนนี้เป็นความเข้าใจที่เข้าใจง่ายของฉันฉันไม่ได้พิสูจน์อย่างเป็นทางการ
อัลกอริทึมนี้ไม่จำเป็นต้องมีจำนวนเต็มขนาดใหญ่เพียงใช้ฟังก์ชั่นการบันทึกบนเลขทศนิยมปกติเท่านั้นดังนั้นมันจึงค่อนข้างมีประสิทธิภาพสำหรับจำนวนมากถึงขีด จำกัด ของการใช้จุดลอยตัว (ไม่ว่าจะเป็นความแม่นยำสองเท่า การใช้งาน 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' ออกมาเป็นค่าที่แน่นอนเพราะมันเป็นหนึ่งในค่าที่ได้รับโดยตรงจากการค้นหาแบบไบนารี ในกรณีทั่วไปที่ไม่ได้เกิดขึ้นดังนั้นผลลัพธ์จะใกล้เคียงกับค่ารูทที่มีข้อผิดพลาด⎕CT (แม่นยำยิ่งขึ้นการทดสอบลอการิทึมของฐานผู้สมัครทุกคนจะดำเนินการด้วยความอดทน⎕CT)