การคำนวณหมายเลข e โดยใช้ Raku


9

ฉันพยายามคำนวณค่าคงที่e ( หมายเลข AKA Euler's ) โดยการคำนวณสูตร อี

เพื่อที่จะคำนวณแฟคทอเรียลและการหารในนัดเดียวฉันเขียนสิ่งนี้:

my @e = 1, { state $a=1; 1 / ($_ * $a++) } ... *;
say reduce  * + * , @e[^10];

แต่มันก็ไม่ได้ผล ทำอย่างไรให้ถูกต้อง?


ในทางใด: "มันไม่ได้ผล"?
SherylHohman

1
ส่วนที่เป็นส่วนหนึ่งในโค้ดตัวอย่างนั้นไม่ได้ผลเพราะมันใช้ประโยชน์จาก ตัวแปรค่าก่อนหน้า $_ในความพยายามที่จะสร้างแฟคทอเรียล เห็นได้ชัดว่าซ้ำซ้อน ในโซลูชันที่ถูกต้องด้านล่าง$_ตกและทำงานอย่างสมบูรณ์
Lars Malmsteen

ขอบคุณ ฉันเดาว่าฉันกำลังมองหาสิ่งที่ถูกต้องมากขึ้นโดยคำสั่งที่ เหมือนมีข้อผิดพลาดอย่างไรไม่สอดคล้องกับสิ่งที่คุณคาดหวังของสิ่งนั้น ฉันเดาว่าการคำนวณของคุณไม่ตรงกับคำตอบที่รู้จักสำหรับการคำนวณนั้น ดีใจที่คุณเข้าใจมันออกมาได้ !! นอกจากนี้คำอธิบายโพสต์คำตอบที่ดีเกี่ยวกับปัญหาที่เกิดขึ้นจริงคือ :-)
SherylHohman

คำตอบ:


11

ผมวิเคราะห์รหัสของคุณในส่วนของการวิเคราะห์รหัสของคุณ ก่อนหน้านั้นฉันขอนำเสนอเนื้อหาเกี่ยวกับโบนัสสองสามส่วน

หนึ่งซับหนึ่งตัวอักษร1

say e; # 2.718281828459045

"บทความหลายวิธี" 2

คลิกที่ลิงก์ด้านบนเพื่อดูบทความพิเศษของ 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 $), เซนต์คิตส์และเนวิสสภาพ ฉันทำมันก่อนที่เพิ่มขึ้นแทนการโพสต์เพิ่มขึ้นเพื่อให้บรรลุผลเช่นเดียวกับคุณได้โดยเริ่มต้นที่จะ$a1

ตอนนี้เรามีปัญหาสุดท้าย (ใหญ่!) ชี้ให้คุณเห็นในความคิดเห็นด้านล่าง

หากไม่มีตัวถูกดำเนินการของมันคือNum(ลอยและประมาณ) /ผู้ปฏิบัติงานตามปกติจะส่งกลับความถูกต้อง 100% Rat(มีเหตุผลความแม่นยำ จำกัด ) แต่ถ้าตัวหารของผลลัพธ์เกิน 64 บิตผลลัพธ์นั้นจะถูกแปลงเป็นNum- ซึ่งเป็นการแลกเปลี่ยนประสิทธิภาพเพื่อความแม่นยำการแลกเปลี่ยนที่เราไม่ต้องการ เราต้องคำนึงถึงเรื่องนั้นด้วย

ในการระบุความแม่นยำไม่ จำกัดเช่นเดียวกับความแม่นยำ 100% เพียงบังคับการดำเนินการเพื่อใช้FatRats ในการทำสิ่งนี้อย่างถูกต้องเพียงให้ (อย่างน้อย) หนึ่งในตัวถูกดำเนินการเป็น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


ขอบคุณสำหรับคำตอบ หัวข้อที่ชื่อว่าMy way ตามวิธีการของคุณแก้ปัญหาได้ค่อนข้างดี ฉันต้องค้นหาความซับซ้อนด้วยซ้ำ ฉันไม่ทราบว่าธรรมดา$เป็นชวเลขสำหรับstate $มันค่อนข้างมีประโยชน์
Lars Malmsteen

มีวิธีในการระบุจำนวนหลักeสำหรับการแก้ปัญหาที่ 3 (บรรดาศักดิ์ทางของฉันขึ้นอยู่กับวิธีการของคุณ )? ฉันได้ลองเพิ่ม FatRat (500) ติดกับ 1 ใน: ... given 1.FatRat(500), ...เพื่อทำให้ตัวเลขแม่นยำ 500 หลัก แต่ไม่ได้ผล
Lars Malmsteen

@LarsMalmsteen ฉันได้ตอบFatRatคำถามสำคัญของคุณในหัวข้อสุดท้ายแล้ว ฉันยังได้เพิ่มคำตอบทั้งหมดแม้ว่าการเปลี่ยนแปลงครั้งสำคัญเพียงอย่างเดียวคือFatRatสิ่งต่างๆ (Btw ฉันตระหนักดีว่ามากของคำตอบของฉันมันสัมผัสกับคำถามเดิมของคุณผมเชื่อว่าท่านไม่ได้ใจผมเขียนทั้งหมดปุยเสริมสร้างความบันเทิงให้กับตัวเองและอาจจะน่าสนใจให้กับผู้อ่านในภายหลัง.)
raiph

ขอบคุณสำหรับความพยายามเป็นพิเศษ ดังนั้น.FatRatส่วนขยายจะต้องใส่ไว้ในตัวสร้างโค้ด ตอนนี้ฉันลองFatRatเพิ่มด้วยวิธีนี้แล้วมันคำนวณeถึงความแม่นยำ 1000+ หลัก ขนปุยที่เพิ่มเข้ามานั้นเป็นของ wort ในขณะนั้น เช่นฉันไม่รู้ว่าsayมันถูกตัดทอนอาร์เรย์ / ลำดับยาว ๆ บิตของข้อมูลดังกล่าวดีที่รู้
Lars Malmsteen

@ LarsMalmsteen :) "ดังนั้น.FatRatส่วนขยายจะต้องใส่ไว้ในตัวสร้างโค้ด". ใช่. โดยทั่วไปหากการแสดงออกที่เกี่ยวข้องกับการแบ่งได้รับการประเมินแล้วมันก็สายเกินไปที่จะยกเลิกความเสียหายที่เกิดขึ้นหากRatความแม่นยำล้น หากมีก็จะมีการประเมินไปNum(ลอย) และในทางกลับกันการคำนวณ taints เพิ่มเติมใด ๆ ที่เกี่ยวข้องกับมันทำให้พวกเขายัง Numวิธีเดียวที่จะให้แน่ใจว่าสิ่งที่เข้าพักFatRatคือการเริ่มต้นพวกเขาFatRatและหลีกเลี่ยงการใด ๆNums Ints และRats ก็โอเคถ้ามีอย่างน้อยก็FatRatให้ Raku รู้ที่จะยึดติดกับFatRats
raiph

9

$_มีเศษส่วนคือ ทำให้คุณต้องหรือมากกว่า1 / (1/$_ * $a++)$_ /$a++

โดย Raku คุณสามารถทำการคำนวณทีละขั้นตอนนี้ได้

1.FatRat,1,2,3 ... *   #1 1 2 3 4 5 6 7 8 9 ...
andthen .produce: &[*] #1 1 2 6 24 120 720 5040 40320 362880
andthen .map: 1/*      #1 1 1/2 1/6 1/24 1/120 1/720 1/5040 1/40320 1/362880 ...
andthen .produce: &[+] #1 2 2.5 2.666667 2.708333 2.716667 2.718056 2.718254 2.718279 2.718282 ...
andthen .[50].say      #2.71828182845904523536028747135266249775724709369995957496696762772

ดี andthenฉันมีความคิดไม่
Holli
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.