如何使用布冯针在tkinter中计算pi?

时间:2019-05-31 14:26:22

标签: python tkinter pi

我知道有很多关于如何使用Buffon's needles来计算pi的教程,但是我在tkinter中没有找到任何教程。

我是一个初学者,对脏代码很抱歉,但是稍后我将带您逐步了解。

绘制设置后,它将为直线的起点生成随机的x1和y1坐标。请注意,我希望线长为50个单位。因此,我生成了x_rel,其范围在-50到50之间。之后,使用毕达哥拉斯定理,我计算了y_rel。可以随机将其设为负,也可以保持正。要获得行的结束坐标,只需将x_relx1相加,即y。

为了检测与板上起始线之一的碰撞,我比较了y1和y2的第一个数字。如果它们相同,则不会发生冲突(这是可行的,因为板上的每条起始线之间的间隙为100)。计算完冲突后,我只需计算pi并打印即可。但它通常返回〜2,6。但是我在网上找到的其他类似程序可以用这种方法计算出pi的准确度。我的错误在哪里?

import tkinter as tk
import random
import math


count = 0
class App:

    def __init__(self, root):

        self.root = root
        root.title("PI calculator")

        c = tk.Canvas(root, height=700, width=700)
        c.pack()
        c.create_line(100, 100, 600, 100)
        c.create_line(100, 200, 600, 200)
        c.create_line(100, 300, 600, 300)
        c.create_line(100, 400, 600, 400)
        c.create_line(100, 500, 600, 500)
        c.create_line(100, 600, 600, 600)
        for x in range(100000):
            c.create_line(self.generate_coords(), fill="red", width=1.5)

    def generate_coords(self):
        choices = [1, 0]
        x1 = random.randint(100, 600)
        y1 = random.randint(100, 600)
        x_rel = random.randint(-50, 50)
        y_rel = math.sqrt(50**2 - x_rel**2)
        if random.choice(choices) == 1:
            y_rel = -abs(y_rel)
        if random.choice(choices) == 0:
            y_rel = abs(y_rel)
        x2 = x1 + x_rel
        y2 = y1 + y_rel
        col = self.detect_collision(y1, y2)
        if col == True:
            global count
            count += 1
        return x1, y1, x2, y2

    def detect_collision(self, y1, y2):
        first_num_1 = math.floor(y1/100)
        first_num_2 = math.floor(y2 / 100)
        if first_num_1 != first_num_2:
            return True
        else:
            return False


root = tk.Tk()
window = App(root)
pi = (2*50*100000)/(100*count)
print(count)
print(pi)
root.mainloop()

38243
2.6148576210025363

1 个答案:

答案 0 :(得分:0)

我试用了您的代码,并将其与类似的程序进行了比较,得出的结论是,您的图钉掉落没有应有的随机性,这使您的结果不正确。下面,我重新设计了掉线逻辑,结果似乎有所改善:

import tkinter as tk
import random
import math

NUMBER_STICKS = 250
LINE_DISTANCE = 100
STICK_LENGTH = 83

class App:

    def __init__(self, root):

        self.root = root
        root.title("PI calculator")

        self.collisions = 0

        c = tk.Canvas(root, height=700, width=700)
        c.pack()

        for y in range(1, 7):
            c.create_line(100, y * LINE_DISTANCE, 600, y * LINE_DISTANCE)

        for _ in range(NUMBER_STICKS):
            collision, *coords = self.generate_coords()
            c.create_line(coords, fill="red" if collision else "green", width=1.5)

    def generate_coords(self):

        x1 = random.randint(100, 600)
        y1 = random.randint(100, 600)

        angle = random.randrange(360)
        x2 = x1 + STICK_LENGTH * math.cos(math.radians(angle))
        y2 = y1 + STICK_LENGTH * math.sin(math.radians(angle))

        collision = self.detect_collision(y1, y2)

        if collision:
            self.collisions += 1

        return collision, x1, y1, x2, y2

    def detect_collision(self, y1, y2):
        num_1 = y1 // LINE_DISTANCE
        num_2 = y2 // LINE_DISTANCE

        return num_1 != num_2

    def get_collisions(self):
        return self.collisions


root = tk.Tk()
application = App(root)

collisions = application.get_collisions()
print((2 * STICK_LENGTH * NUMBER_STICKS) / (LINE_DISTANCE * collisions))

root.mainloop()

输出

% python3 test.py
3.516949152542373
%

我还修改了程序,以将引脚的颜色编码为交叉或不交叉:

enter image description here