树莓派计算器输出问题

3

我已经创建了一个简单的Python程序,通过计算适合圆形内的1像素点数量来计算pi。一开始,我使用以下值运行程序:

from tkinter import *

tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()

canvas.create_oval(100,100,400,400)

global pi_count
pi_count = 0

for x in range(100,400):
    for y in range(100,400):
        point = canvas.create_oval(x,y,(x+1),(y+1))
        c = canvas.coords(point)
        sc = list(c)
        xc = sc[1]
        yc = sc[2]
        fxc = int(xc)
        fyc = int(yc)
        dist = ((fxc - 250)**2 + (fyc - 250)**2)**0.5
        if dist > 150:
            print("outside of the circle")
        else:
            pi_count += 1
        print(pi_count)

pi = (pi_count/150**2)
print(pi)

这给我输出了3.1412888889。

对于这个结果相对满意,我改变了椭圆的尺寸为 (100,100,500,500),并相应地改变了所有其他值(半径、循环等)。

然而,这个更大的圆形和可能更精确的面积产生了一个更不准确的估计值3.140675。

这是为什么?我该如何修正计算器以给出更精确的估计?

编辑

以下是已编辑和改进的代码,更易于测试:

from tkinter import *

MIN_POS = 100
MAX_POS = 300
center = (MAX_POS + MIN_POS)/2
radius = (MAX_POS - MIN_POS)/2

tk = Tk()
canvas = Canvas(tk, width=MAX_POS, height=MAX_POS)
canvas.pack()

canvas.create_oval(MIN_POS,MIN_POS,MAX_POS,MAX_POS)

global pi_count
pi_count = 0

for x in range(MIN_POS,MAX_POS):
    for y in range(MIN_POS,MAX_POS):
        point = canvas.create_oval(x,y,(x+1),(y+1))
        c = canvas.coords(point)
        sc = list(c)
        xc = sc[1]
        yc = sc[2]
        fxc = int(xc)
        fyc = int(yc)
        dist = ((fxc - center)**2 + (fyc - center)**2)**0.5
        if dist > radius:
            print("outside of the circle")
        else:
            pi_count += 1
        print(pi_count)

pi = (pi_count/radius**2)
print(pi)

如果有一台快速的电脑可以按照100的步长提高Max_pos值来运行此程序,我会非常感激。


大数据集(更大的圆圈)? - Klaus D.
3
你把每个“400”都改成“500”了吗?像这样的神奇数字很危险,使用命名常量。有可能你只改了部分“400”。 - Andras Deak -- Слава Україні
1
同样适用于 250,它可能来自于 (100+400)/2 - Andras Deak -- Слава Україні
2
让我们在聊天中继续这个讨论 - Andras Deak -- Слава Україні
1
如果您不显示点数,那么您的“更快”代码将会快得多。计算本身可以在内存中完成。 - Jongware
显示剩余7条评论
1个回答

1
这种方法非常不准确。测试一个半径的结果可能比少1或多1的半径的结果相差很大:
100 -> 3.141700 ~ 1.000034
125 -> 3.140928 ~ 0.999788
150 -> 3.141378 ~ 0.999932
175 -> 3.141518 ~ 0.999976
200 -> 3.140725 ~ 0.999724
225 -> 3.141393 ~ 0.999936
250 -> 3.141136 ~ 0.999855
275 -> 3.140826 ~ 0.999756
300 -> 3.141078 ~ 0.999836
325 -> 3.141311 ~ 0.999910
350 -> 3.140939 ~ 0.999792
375 -> 3.141582 ~ 0.999997
400 -> 3.141406 ~ 0.999941

原因在于您只测试整数值,因此这些值倾向于向下舍入。虽然增加半径确实可以提高精度,但在足够小数位数的情况下,要获得π应该是不可能的,直到超出Python浮点精度的限制-我不知道需要多大的半径才能实现这一点。
对于您的值150,测试149和151同样表明它们都不是“更好”的;两者都要差得多!
150 -> 3.141378 ~ 0.999932
 -1 -> 3.140804 ~ 0.999749
 +1 -> 3.140783 ~ 0.999742

即使半径很大,例如10,000,您仍然可以得到3.141591〜0.999999(计算需要一段时间)。
使用以下代码进行测试(不使用图形显示)。请注意,您的代码中有一个小错误,这也会影响结果!您运行(100,400)范围,您可能也可以将其写为(0,300)。减去半径,您有(-150,150) - 但是Python的range函数从{{link1:start小于 stop}}运行。这意味着您正在计算-150..-1,然后是0,然后是1..149,并且存在小偏差向左。
(但是,考虑到这一点并不能明显提高准确性。)
import math

def calc_pi(radius):
    pi_count = 0
    rad2 = radius*radius
    for x in range(-radius,radius+1):
        x2 = x*x
        for y in range(-radius,radius+1):
            dist = x2 + y*y
            if dist <= rad2:
                pi_count += 1
    return float(pi_count)/radius**2

for i in range(100,401,25):
    result = calc_pi(i)
    print("%d -> %f ~ %f" % (i, result, result/math.pi))

我已经使用更新的代码编辑了帖子@usr2564301。 - 3141

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接