Quiche Lorraine [ปิด]


52

เพราะมันเป็นวัน Pi เมื่อเร็ว ๆ นี้ผมได้สังเกตเห็นจำนวนของความท้าทายที่ขอให้คุณสามารถคำนวณปี่

แน่นอนลอร์เรนคีชนั้นค่อนข้างไม่เป็นวงกลม (คุณสามารถรับคะแนนโบนัส¹ของ +1 หากคุณคาดเดาความท้าทายของชื่อ) ดังนั้นงานของคุณคือการเขียนอัลกอริธึมหรือวิธีการที่ดูเหมือนว่ามันจะใกล้เคียงกับ Pi ในตอนแรก แต่รับประกันได้ว่าจะไม่เข้าหา Pi

นี่เป็นความท้าทายที่อยู่ภายใต้การดูแลดังนั้นโปรดตรวจสอบให้แน่ใจว่ามันจะออก 3.14 ... สำหรับกรณีทดสอบอย่างง่ายเช่นมีการทำซ้ำ 10 อัลกอริทึมของคุณ นี่เป็นความท้าทายที่ได้รับความนิยมดังนั้นอย่าไปให้ชัดเจนecho(pi)และบอกว่าจุดลอยตัวของ IEEE 754 ปัดตัวเลขขึ้นหรือลง

ผู้ชนะจะได้รับลอร์เรนคีช

¹คำเตือน: ไม่ใช่คะแนนโบนัส โดยอ้างว่าคะแนนคุณตกลงที่จะอบฉันพายก่อน Pi Day, 2016

² คำเตือน: ลอเรน quiche ใช้เป็นคำเปรียบเทียบสำหรับการทำเครื่องหมายคำตอบของคุณเป็น 'ยอมรับ'


ที่เกี่ยวข้อง: การเชื่อมโยง
SP3000

2
ฉันลงคะแนนเพื่อปิดคำถามนี้เป็นนอกหัวข้อเนื่องจากความท้าทายที่ไม่ได้อยู่ภายใต้หัวข้อนี้อีกต่อไป meta.codegolf.stackexchange.com/a/8326/20469
แมว

คำตอบ:


77

ขั้นตอนวิธี

การใช้ผลลัพธ์ที่รู้จักกันดี:

ป้อนคำอธิบายรูปภาพที่นี่

เรากำหนดไว้ใน Python 3:

from math import sin
from functools import reduce
from operator import mul

def integrate(f, a, b, n):
   h = (b-a)/n
   i = h * sum(f(a+i*h+h/2) for i in range(n))
   return i

def sinc(x):
   return sin(x)/x

def borwein(n):
   def f(x):
     g = lambda i: sinc(x/(2*i+1))
     return reduce(mul, map(g, range(n)), 1)
   return f

การทดสอบ

>>> for i in range(1,10):
...   pi = 2 * integrate(borwein(i), 0, 1000, 1000)
...   print("x[{}] = {}".format(i, pi))
x[1] = 3.140418050361841
x[2] = 3.141593078648859
x[3] = 3.1415926534611547
x[4] = 3.1415926535957164
x[5] = 3.1415926535895786
x[6] = 3.1415926535897953
x[7] = 3.1415926535897936
x[8] = 3.1415926535435896 # ???
x[9] = 3.141592616140805  # ?!!

ผู้ทำให้เสื่อมเสีย

Borwein หนึ่งคือแนวความคิดทางคณิตศาสตร์ของเล่นตลก ในขณะที่ตัวตนข้างต้นถือได้ถึง sinc (x / 13) ค่าต่อไปคือจริง:

ป้อนคำอธิบายรูปภาพที่นี่


12
อาจเป็นหนึ่งในคำตอบที่ดีที่สุดสำหรับคำถามที่แฝงตัวในครั้งล่าสุด
เครื่องมือเพิ่มประสิทธิภาพ

14
"ความคิดทางคณิตศาสตร์ของเรื่องตลกในทางปฏิบัติ" +1
ข้าวเกรียบ

16
นั่นเป็นสิ่งที่ดี! IIRC หนึ่งในเรื่องตลกที่เป็นที่รู้จักมากขึ้นของอินทิกรัลนี้คือเมื่อมีคนบันทึกผลลัพธ์ถึงตัวประหลาดใน Wolfram Alpha และส่งรายงานข้อผิดพลาด ... ซึ่ง devs WA ใช้เวลานานในการพยายามแก้ไข =)
Mints97

3
การอ้างอิงนี้ให้คำอธิบายที่ดีเกี่ยวกับสิ่งที่เกิดขึ้น
TonioElGringo

59

ในการค้นหา pi เราจะรวมสมการเชิงอนุพันธ์ที่รู้จักกันดีนี้:

> dy / dt = sin (y) * exp (t)

ด้วยเงื่อนไขเริ่มต้น

> 0 <y0 <2 * pi

เป็นที่ทราบกันดีว่าปัญหาค่าเริ่มต้นนี้มาถึง conver เมื่อ t เพิ่มขึ้นโดยไม่มีการผูก ดังนั้นสิ่งที่เราต้องมีคือเริ่มต้นด้วยการคาดเดาที่สมเหตุสมผลสำหรับบางอย่างระหว่าง 0 ถึง2πและเราสามารถทำการรวมเชิงตัวเลขได้ 3 ใกล้กับπดังนั้นเราจะเลือก y = 3 เพื่อเริ่ม

class PiEstimator {

    static final int numSteps = 100;
    static final double dt = 0.1, tMax = numSteps * dt;

    static double f(double y, double t){ return Math.sin(y) * Math.exp(t); }

    public static void main(String[] args){
        double y = 3;
        int n = 0;

        for(double t = 0; t < tMax; t+=dt){
            if(n%5 == 0) System.out.println(n + ": " + y);
            n++;
            y += f(y,t)*dt;
        }
    }
}

นี่คือผลลัพธ์บางส่วนสำหรับแต่ละขั้นตอนที่ต่างกัน:

0: 3.0
5: 3.0682513992369205
10: 3.11812938865782
15: 3.1385875952782825
20: 3.141543061526081
25: 3.141592653650948
30: 3.1415926535886047
35: 3.1415926535970526
40: 3.1415926517316737  // getting pretty close!
45: 3.1416034165087647  // uh oh
50: 2.0754887983317625  
55: 49.866227663669584
60: 64.66835482328707
65: 57.249212987256286
70: 9.980977494635624
75: 35.43035516640032
80: 51.984982646834
85: 503.8854575676292
90: 1901.3240821223753
95: 334.1514462091029
100: -1872.5333656701248

มันทำงานอย่างไร:

สมการเชิงอนุพันธ์นั้นเป็นที่รู้จักกันดีเพราะเป็นการยากที่จะรวมอย่างถูกต้อง ในขณะที่ค่า t เล็กน้อยไร้เดียงสาบูรณาการจะให้ผลลัพธ์ที่ยอมรับได้วิธีการรวมส่วนใหญ่แสดงความไม่แน่นอนมากเมื่อ t มีขนาดใหญ่มาก


4
@UriZarfaty บทความวิกิพีเดียนี้อธิบายได้ค่อนข้างดี: en.wikipedia.org/wiki/Stiff_equation
AJMansfield

1
คือnอะไร ...
โคลจอห์นสัน

1
@JMansfield ฉันหมายถึง: มันไม่ได้ประกาศที่ไหนเลย คุณforชะลอตัวใช้แต่ห่วงของคุณใช้t n
โคลจอห์นสันมี. ค.

1
@ ColeJohnson ฉันเพิ่งแก้ไขได้
AJMansfield

2
ฉันคิดว่าสมการเชิงอนุพันธ์ของคุณควรอ่าน dy / dt = sin (y) * exp (t)
David Zhang

6

รหัส:

var pi = function(m) {
  var s2 = 1, s1 = 1, s = 1;
  for (var i = 0; s >= 0; ++i) {
    s = s1 * 2 - s2 * (1 + m*m);
    s2 = s1;
    s1 = s;
  }
  return i*m*2;
};

โดยทั่วไปฉันค้นพบลำดับนี้โดยไม่ได้ตั้งใจ มันเริ่มต้นจากการเป็น1, 1และระยะเวลาหลังจากนั้นทุกคนจะได้รับจากs(n) s(n) = 2*s(n - 1) - s(n - 2) * (1 + m*m)ผลลัพธ์ที่ได้คือมีขนาดเล็กที่สุดnเช่นที่คูณด้วยs(n) < 0 2mเมื่อmมีขนาดเล็กลงควรมีความแม่นยำมากขึ้น

pi(1/100) --> 3.14
pi(1/1000) --> 3.14
pi(1/10000) --> 3.1414
pi(1/100000) --> 3.14158
pi(1/1000000) --> 3.141452 // what?
pi(1/10000000) --> 3.1426524 // .. further away from pi

ฉันค่อนข้างแน่ใจว่าสิ่งเหล่านี้เป็นข้อผิดพลาดของจุดลอยเมื่อ(1 + m*m)เข้าใกล้จุดหนึ่ง แต่ฉันไม่แน่ใจ อย่างที่ฉันบอกว่าฉันบังเอิญเจอสิ่งนี้โดยบังเอิญ ฉันไม่แน่ใจชื่อทางการ อย่าลองด้วยmขนาดเล็กเกินไปหรือมันจะทำงานตลอดไป (ถ้า1 + m*m == 1เนื่องจากmมีขนาดเล็กมาก)

หากใครรู้ชื่อของลำดับนี้หรือทำไมมันทำงานเช่นนี้ฉันจะขอบคุณมัน


ฉันคิดว่านี่เป็นเพราะการยกเลิกซึ่งเป็นการสูญเสียตัวเลขเมื่อลบจำนวนที่เกือบเท่ากับสองจำนวน S1 และ s2 เกือบเท่ากันหลังจากการทำซ้ำ
Sanchises

1
ฉันยังไม่ทราบว่ามันทำงานอย่างไร แต่มันทำให้ฉันนึกถึงบางสิ่งบางอย่างที่ฉันเคยทำ: ฉันเอาผลรวมสะสมของสัญญาณรบกวนและทำการทำให้เป็นมาตรฐาน 0 หมายถึงค่าสูงสุด 1 สิ่งนี้จะมาบรรจบกับคลื่นไซน์ เนื่องจากเป็นสัญญาณเดียวที่เป็นตัวต่อต้านอนุพันธ์ (ที่มีเฟสออฟเซ็ต)
Sanchises

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