ผมวิเคราะห์รหัสของคุณในส่วนของการวิเคราะห์รหัสของคุณ ก่อนหน้านั้นฉันขอนำเสนอเนื้อหาเกี่ยวกับโบนัสสองสามส่วน
หนึ่งซับหนึ่งตัวอักษร1
say e; # 2.718281828459045
คลิกที่ลิงก์ด้านบนเพื่อดูบทความพิเศษของ Damian Conway เกี่ยวกับการใช้คอมพิวเตอร์e
ใน Raku
บทความนี้สนุกมาก (หลังจากนั้นก็คือ Damian) e
มันเป็นความเข้าใจการอภิปรายมากในการคำนวณ และเป็นการแสดงความเคารพต่อการกลับชาติมาเกิดใหม่ของปรัชญา RIM ของ TIMTOWTDI ที่ Larry Wall นำมาใช้ 3
ในฐานะที่เป็นอาหารเรียกน้ำย่อยนี่เป็นคำพูดที่มาจากบทความประมาณครึ่งทาง:
เนื่องจากวิธีการที่มีประสิทธิภาพเหล่านี้ทั้งหมดทำงานในลักษณะเดียวกัน - โดยการสรุป (ส่วนย่อยเริ่มต้นของ) ชุดคำที่ไม่สิ้นสุด - อาจจะดีกว่าถ้าเรามีฟังก์ชั่นที่จะทำเพื่อเรา และมันคงจะดีกว่านี้ถ้าฟังก์ชั่นสามารถทำงานได้ด้วยตัวเองว่าชุดย่อยเริ่มต้นของซีรีส์นั้นจำเป็นต้องมีอะไรบ้างเพื่อให้ได้คำตอบที่ถูกต้อง ... แทนที่จะต้องการให้เราจัดการผลของ การทดลองหลายครั้งเพื่อค้นพบสิ่งนั้น
และบ่อยครั้งที่ใน Raku มันง่ายที่จะสร้างสิ่งที่เราต้องการอย่างน่าประหลาดใจ:
sub Σ (Unary $block --> Numeric) {
(0..∞).map($block).produce(&[+]).&converge
}
วิเคราะห์รหัสของคุณ
นี่คือบรรทัดแรกที่สร้างซีรี่ส์:
my @e = 1, { state $a=1; 1 / ($_ * $a++) } ... *;
การปิด ( { code goes here }
) คำนวณคำศัพท์ การปิดมีลายเซ็นไม่ว่าจะโดยนัยหรือชัดแจ้งซึ่งจะกำหนดจำนวนข้อโต้แย้งที่จะยอมรับ ในกรณีนี้ไม่มีลายเซ็นชัดเจน การใช้งานของ$_
( ว่า "หัวข้อ" ตัวแปร ) $_
ผลลัพธ์ในลายเซ็นนัยที่ต้องใช้อาร์กิวเมนต์หนึ่งที่ผูกไว้กับ
ตัวดำเนินการลำดับ ( ...
) เรียกการปิดซ้ำ ๆ ทางด้านซ้ายผ่านเทอมก่อนหน้าเป็นอาร์กิวเมนต์ของการปิดเพื่อสร้างชุดคำศัพท์ขึ้นอย่างเฉื่อยชาจนจุดสิ้นสุดทางด้านขวาซึ่งในกรณีนี้คือ*
ชวเลขสำหรับInf
อาคาอินฟินิตี้
1
หัวข้อในสายแรกที่ปิดคือ ดังนั้นการปิดทำการคำนวณและส่งกลับที่1 / (1 * 1)
ให้สองเทอมแรกในซีรีย์1, 1/1
ดังนี้
หัวข้อในการโทรครั้งที่สองคือค่าของการโทรก่อนหน้า1/1
คือ1
อีกครั้ง ดังนั้นคำนวณปิดและผลตอบแทนการขยายชุดที่1 / (1 * 2)
1, 1/1, 1/2
ทุกอย่างดูดี
คำนวณปิดต่อไปซึ่งเป็น1 / (1/2 * 3)
ระยะที่ควรจะเป็น0.666667
1 / (1 * 2 * 3)
อุ่ย
ทำให้รหัสของคุณตรงกับสูตร
รหัสของคุณควรตรงกับสูตร:
ในสูตรนี้แต่ละคำจะถูกคำนวณตามตำแหน่งในชุด k TH ระยะในซีรีส์ (ที่k = 0 สำหรับครั้งแรก1
) เป็นเพียงปัจจัยk 's ซึ่งกันและกัน
(ดังนั้นจึงไม่มีอะไรเกี่ยวข้องกับมูลค่าของเทอมก่อนดังนั้น$_
ซึ่งไม่ควรใช้ในการปิดเทอมก่อนหน้านี้ซึ่งได้รับคุณค่าของเทอมก่อน)
มาสร้างตัวดำเนินการ postfix แบบแฟกทอเรียล
sub postfix:<!> (\k) { [×] 1 .. k }
( ×
เป็นตัวดำเนินการคูณ infix ซึ่งเป็นนามแฝงที่ดูดีกว่าUnicodeของ ASCII infix *
ทั่วไป)
จดชวเลขสำหรับ:
sub postfix:<!> (\k) { 1 × 2 × 3 × .... × k }
(ฉันใช้สัญกรณ์ metasyntactic หลอกในวงเล็บปีกกาเพื่อแสดงความคิดในการเพิ่มหรือลบคำมากเท่าที่ต้องการ
โดยทั่วไปผู้ประกอบการวางมัดในวงเล็บที่เริ่มต้นของการแสดงออกรูปแบบผู้ประกอบการคำนำหน้าคอมโพสิตที่เทียบเท่าของop
reduce with => &[op],
ดูข้อมูลเพิ่มเติมที่metaoperator
ตอนนี้เราสามารถเขียนปิดเพื่อใช้ตัวดำเนินการ postfix factorial ใหม่:
my @e = 1, { state $a=1; 1 / $a++! } ... *;
การเล่นชนิดหนึ่ง สิ่งนี้สร้างซีรี่ส์ที่เหมาะสม
... จนกว่าจะทำไม่ได้ด้วยเหตุผลอื่น ปัญหาต่อไปคือความแม่นยำเชิงตัวเลข แต่ขอจัดการกับมันในหัวข้อถัดไป
ซับหนึ่งมาจากรหัสของคุณ
อาจบีบอัดสามบรรทัดลงหนึ่ง:
say [+] .[^10] given 1, { 1 / [×] 1 .. ++$ } ... Inf
.[^10]
given
นำไปใช้กับหัวข้อซึ่งเป็นที่ที่กำหนดโดย ( ^10
ย่อมาจาก0..9
ดังนั้นรหัสข้างต้นคำนวณผลรวมของสิบคำแรกในซีรีส์)
ฉันได้ตัดออก$a
จากการคำนวณปิดในเทอมหน้าแล้ว โดดเดียว$
กับ(state $)
, เซนต์คิตส์และเนวิสสภาพ ฉันทำมันก่อนที่เพิ่มขึ้นแทนการโพสต์เพิ่มขึ้นเพื่อให้บรรลุผลเช่นเดียวกับคุณได้โดยเริ่มต้นที่จะ$a
1
ตอนนี้เรามีปัญหาสุดท้าย (ใหญ่!) ชี้ให้คุณเห็นในความคิดเห็นด้านล่าง
หากไม่มีตัวถูกดำเนินการของมันคือNum
(ลอยและประมาณ) /
ผู้ปฏิบัติงานตามปกติจะส่งกลับความถูกต้อง 100% Rat
(มีเหตุผลความแม่นยำ จำกัด ) แต่ถ้าตัวหารของผลลัพธ์เกิน 64 บิตผลลัพธ์นั้นจะถูกแปลงเป็นNum
- ซึ่งเป็นการแลกเปลี่ยนประสิทธิภาพเพื่อความแม่นยำการแลกเปลี่ยนที่เราไม่ต้องการ เราต้องคำนึงถึงเรื่องนั้นด้วย
ในการระบุความแม่นยำไม่ จำกัดเช่นเดียวกับความแม่นยำ 100% เพียงบังคับการดำเนินการเพื่อใช้FatRat
s ในการทำสิ่งนี้อย่างถูกต้องเพียงให้ (อย่างน้อย) หนึ่งในตัวถูกดำเนินการเป็นFatRat
(และไม่มีคนอื่นเป็นNum
):
say [+] .[^500] given 1, { 1.FatRat / [×] 1 .. ++$ } ... Inf
ฉันตรวจสอบนี้ถึง 500 หลักทศนิยม ฉันคาดว่ามันจะยังคงถูกต้องจนกว่าโปรแกรมจะขัดข้องเนื่องจากเกินขีด จำกัด ของภาษา Raku หรือคอมไพเลอร์ Rakudo (ดูคำตอบของฉันที่จะไม่สามารถยกเลิกการใส่ Bigint แบบกว้าง 65536 บิตเป็นจำนวนเต็มพื้นฐานสำหรับการอภิปรายบางส่วนได้)
เชิงอรรถ
1 Raku มีไม่กี่ค่าคงที่ทางคณิตศาสตร์ที่สำคัญในตัวรวมทั้งe
, i
และpi
(และนามแฝงของมันπ
) ดังนั้นเราจึงสามารถเขียนอัตลักษณ์ของออยเลอร์ใน Raku ได้เหมือนในหนังสือคณิตศาสตร์ ด้วยการให้เครดิตกับรายการ Raku ของ RosettaCode สำหรับข้อมูลประจำตัวของออยเลอร์ :
# There's an invisible character between <> and iπ character pairs!
sub infix:<> (\left, \right) is tighter(&infix:<**>) { left * right };
# Raku doesn't have built in symbolic math so use approximate equal
say e**iπ + 1 ≅ 0; # True
2บทความของ Damian ต้องอ่าน แต่มันก็เป็นเพียงหนึ่งในการรักษาที่น่าชื่นชมหลายอย่างที่อยู่ในหมู่ 100 + ไม้ขีดไฟสำหรับGoogle สำหรับ 'Raku "จำนวนออยเลอร์'
3ดูTIMTOWTDI กับ TSBO-APOO-OWTDIสำหรับหนึ่งในมุมมองที่สมดุลมากขึ้นของ TIMTOWTDI ที่เขียนโดยแฟน ๆ ของหลาม แต่มีข้อเสียคือการใช้ TIMTOWTDI มากเกินไป เพื่อสะท้อนให้เห็นถึง "อันตราย" หลังนี้ชุมชน Perl ประกาศเกียรติคุณTIMTOWTDIBSCINABTE ที่ตลกขบขันและไม่สามารถเข้าใจได้- มีมากกว่าหนึ่งวิธีที่จะทำ แต่บางครั้งความสอดคล้องไม่ได้เลวร้ายอย่างใดอย่างหนึ่ง แปลกพอแลร์รี่นำมาประยุกต์ใช้ในการออกแบบไบคาร์บอเนต Raku และเดเมียนนำไปใช้กับคอมพิวเตอร์e
ใน Raku