Quiche Lorraine [đóng]


52

Vì nó là Pi ngày gần đây, tôi đã nhận thấy một số các thách thức yêu cầu bạn để tính toán pi.

Tất nhiên, một licheine quiche không hoàn toàn là một chiếc bánh (bạn có thể yêu cầu Điểm thưởng¹ là +1 nếu bạn đoán được thử thách từ tiêu đề). Như vậy, việc của bạn là viết một thuật toán hay phương phápvẻ thích nó xấp xỉ Pi ở cái nhìn đầu tiên, nhưng được bảo đảm không hội tụ về phía Pi.

Đây là một thử thách ngầm, vì vậy hãy đảm bảo rằng nó sẽ xuất ra 3.14 ... cho một trường hợp thử nghiệm đơn giản, ví dụ với 10 lần lặp thuật toán của bạn. Đây cũng là một thách thức phổ biến, vì vậy đừng đi quá rõ ràng echo(pi)và nói rằng điểm nổi IEEE 754 làm tròn một số chữ số lên hoặc xuống.

Người chiến thắng có được một licheine².

Cảnh báo: không thực sự là điểm thưởng. Bằng cách tuyên bố điểm số, bạn đồng ý nướng cho tôi một chiếc bánh trước Ngày Pi, 2016

² Cảnh báo: quiche lorraine được sử dụng như một phép ẩn dụ để câu trả lời của bạn được đánh dấu là 'được chấp nhận'


Liên quan: link
Sp3000 19/03/2015

2
Tôi đang bỏ phiếu để đóng câu hỏi này dưới dạng ngoài chủ đề vì những thách thức ngầm không còn là chủ đề ở đây nữa. meta.codegolf.stackexchange.com/a/8326/20469
mèo

Câu trả lời:


77

Thuật toán

Sử dụng kết quả nổi tiếng:

nhập mô tả hình ảnh ở đây

chúng tôi định nghĩa trong 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

Kiểm tra

>>> 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  # ?!!

Làm hỏng

Các Borwein không thể thiếu là ý tưởng toán học của một trò đùa thực tế. Mặc dù danh tính ở trên giữ đúng mức (x / 13), giá trị tiếp theo thực sự là:

nhập mô tả hình ảnh ở đây


12
Có lẽ là một trong những câu trả lời tốt nhất cho một câu hỏi ngầm trong thời gian gần đây.
Tối ưu hóa

14
"ý tưởng toán học của một trò đùa thực tế". +1
mở cửa

16
Nó là cái tốt! IIRC, một trong những trò đùa nổi tiếng với tích phân này là khi ai đó ghi lại kết quả cho đến kết quả kỳ lạ trên Wolfram Alpha và gửi báo cáo lỗi ... Mà các nhà phát triển WA đã dành nhiều năm cố gắng sửa chữa =)
Mint97

3
Tài liệu tham khảo này đưa ra một lời giải thích tốt về những gì đang xảy ra.
TonioElGringo

59

Để tìm pi, chúng ta sẽ tích hợp phương trình vi phân nổi tiếng này:

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

Với một điều kiện ban đầu

> 0 <y0 <2 * pi

Người ta biết rằng bài toán giá trị ban đầu này hội tụ đến π khi t tăng mà không bị ràng buộc. Vì vậy, tất cả những gì chúng ta cần là bắt đầu với một dự đoán hợp lý cho một cái gì đó trong khoảng từ 0 đến 2π và chúng ta có thể thực hiện tích hợp số. 3 gần với π, vì vậy chúng tôi sẽ chọn y = 3 để bắt đầu.

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;
        }
    }
}

Dưới đây là một số kết quả cho mỗi số bước khác nhau:

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

Làm thế nào nó hoạt động:

Phương trình vi phân đó được biết đến vì cực kỳ khó tích hợp chính xác. Trong khi đối với các giá trị t nhỏ, tích hợp ngây thơ sẽ tạo ra kết quả chấp nhận được, hầu hết các phương pháp tích hợp thể hiện sự không ổn định cực kỳ vì t trở nên rất lớn.


4
@UriZarfaty Bài viết trên wikipedia này giải thích khá hay: en.wikipedia.org/wiki/Stiff_equation
AJMansfield 19/03/2015

1
ngì? ...
Cole Johnson

1
@AJMansfield Ý tôi là: nó không được tuyên bố ở bất cứ đâu. forGiảm tốc của bạn sử dụng t, nhưng vòng lặp của bạn sử dụng n.
Cole Johnson

1
@ColeJohnson Mình mới sửa nó.
AJMansfield

2
Tôi nghĩ rằng phương trình vi phân của bạn nên đọc dy / dt = sin (y) * exp (t).
David Zhang

6

Mã số:

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;
};

Tôi cơ bản phát hiện ra trình tự này một cách tình cờ. Nó bắt đầu như 1, 1và mọi điều khoản sau đó s(n)được đưa ra bởi s(n) = 2*s(n - 1) - s(n - 2) * (1 + m*m). Kết quả cuối cùng là nhỏ nhất nsao cho s(n) < 0nhân với 2m. Khi mcàng nhỏ, nó sẽ càng ngày càng chính xác.

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

Tôi khá chắc chắn đây là những lỗi dấu phẩy động (1 + m*m)gần với một, nhưng tôi không chắc. Như tôi đã nói, tôi tình cờ phát hiện ra điều này. Tôi không chắc tên chính thức của nó. Đừng thử điều này với một cái mquá nhỏ hoặc nó sẽ chạy mãi mãi (nếu 1 + m*m == 1do mquá nhỏ).

Nếu bất cứ ai biết tên của chuỗi này hoặc tại sao nó hoạt động như thế này, tôi sẽ đánh giá cao nó.


Tôi nghĩ rằng điều này là do hủy bỏ, đó là sự mất các chữ số khi trừ hai số gần như bằng nhau. S1 và s2 gần như bằng nhau sau một lần lặp.
Chiếm 4/10/2015

1
Tôi vẫn chưa tìm hiểu làm thế nào nó hoạt động, nhưng nó nhắc tôi về một điều tôi đã từng làm: Tôi liên tục lấy tổng tích lũy của tín hiệu nhiễu và chuẩn hóa nó thành 0, giá trị tối đa 1. Điều này sẽ hội tụ thành một sóng hình sin, vì đó là tín hiệu duy nhất là dẫn xuất riêng của nó (có bù pha).
Chiếm 4/10/2015

Tôi đã hỏi nó tại math.SE, và nhận được câu trả lời này .
Sanchise
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.