You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的Python圆周率计算器运行速度随时间逐渐变慢?

问题:Galperin圆周率模拟程序运行速度急剧下降

我最近看了一段讲解Galperin圆周率计算方法的视频,照着做了个Python模拟程序。程序逻辑没问题,但运行速度越来越慢:一开始每秒能算几百次碰撞,很快降到40-50次,跑久了甚至只剩2次每秒。

以下是我的代码:

# imports
from time import time, sleep
from fractions import Fraction

# set variables
p = [Fraction(8, 1), Fraction(10, 1)]
m = [1, 1]
v = [Fraction(0, 1), Fraction(-1, 1)]
collisions = 0
time_interval = 1

# main
print("The π Calculator\n\nCredits:\nOriginal formula discovered by Gregory Galperin\nSimulation by Te Du\n")
sleep(1)
m[1] = 100 ** int(input("How many digits would you like to calculate? "))
start_time = time()
prev_time = start_time
while not (v[0] <= v[1] and v[0] >= 0):
    if time() - prev_time >= time_interval:
        try:
            print("Seconds elapsed: " + str(time() - start_time) + "\nCollisions: " + str(collisions))
        except ValueError:
            prev_time = time() + 1000000000
        time_interval = 2 - (time() - prev_time)
        prev_time = time()
    try:
        wall_to_one = p[0] / -v[0]
    except ZeroDivisionError:
        wall_to_one = 0
    one_to_two = (p[1] - p[0]) / (v[0] - v[1])
    collisions += 1
    if one_to_two <= 0 or (0 < wall_to_one and wall_to_one < one_to_two):
        p[0] += v[0] * wall_to_one
        p[1] += v[1] * wall_to_one
        v[0] *= -1
    else:
        p[0] += v[0] * one_to_two
        p[1] += v[1] * one_to_two
        v = [Fraction(m[0] - m[1], m[1] + m[0]) * v[0] + Fraction(2 * m[1], m[1] + m[0]) * v[1], Fraction(2 * m[0], m[1] + m[0]) * v[0] + Fraction(m[1] - m[0], m[1] + m[0]) * v[1]]

# cleanup
del p, m, v, wall_to_one, one_to_two, start_time, prev_time, time_interval

# printing pi
print("π: " + str(collisions))

问题根源

  1. fractions.Fraction的性能损耗:随着碰撞次数增加,分数的分子分母会指数级膨胀,每次运算都需要计算大整数的最大公约数(GCD),这会导致运算时间急剧上升。
  2. 不合理的性能监控逻辑:time_interval = 2 - (time() - prev_time)会让打印间隔越来越小,频繁的printIO操作进一步消耗CPU资源。

优化方案

1. 替换Fraction为浮点数(牺牲精度换速度)

浮点数运算为硬件原生支持,速度远快于大整数分数运算,对于10位以内的圆周率计算完全足够:

# 变量初始化改为浮点数
p = [8.0, 10.0]
m = [1, 1]
v = [0.0, -1.0]
...
# 碰撞速度计算简化
total_mass = m[0] + m[1]
v0_new = (m[0] - m[1])/total_mass * v[0] + 2*m[1]/total_mass * v[1]
v1_new = 2*m[0]/total_mass * v[0] + (m[1] - m[0])/total_mass * v[1]
v = [v0_new, v1_new]

2. 优化性能监控逻辑

固定打印间隔,减少IO操作,用f-string提升拼接效率:

print_interval = 1  # 每秒打印一次
start_time = time()
prev_time = start_time
while not (v[0] <= v[1] and v[0] >= 0):
    current_time = time()
    if current_time - prev_time >= print_interval:
        print(f"Seconds elapsed: {current_time - start_time:.2f}\nCollisions: {collisions}")
        prev_time = current_time
    ...

3. 整数镜像模拟(高精度高效方案)

如果需要精确计算更多位数,可利用Galperin模型的对称性,将碰撞转化为镜像反射,全程用整数运算避免分数,彻底消除GCD计算的性能损耗。


优化后代码示例(浮点数版本)

from time import time, sleep

# set variables
p = [8.0, 10.0]
m = [1, 1]
v = [0.0, -1.0]
collisions = 0
print_interval = 1

# main
print("The π Calculator\n\nCredits:\nOriginal formula discovered by Gregory Galperin\nSimulation by Te Du\n")
sleep(1)
digits = int(input("How many digits would you like to calculate? "))
m[1] = 100 ** digits
start_time = time()
prev_time = start_time

while not (v[0] <= v[1] and v[0] >= 0):
    current_time = time()
    if current_time - prev_time >= print_interval:
        print(f"Seconds elapsed: {current_time - start_time:.2f}\nCollisions: {collisions}")
        prev_time = current_time
    
    try:
        wall_to_one = p[0] / -v[0]
    except ZeroDivisionError:
        wall_to_one = 0
    one_to_two = (p[1] - p[0]) / (v[0] - v[1])
    collisions += 1
    
    if one_to_two <= 0 or (0 < wall_to_one and wall_to_one < one_to_two):
        # 撞墙
        p[0] += v[0] * wall_to_one
        p[1] += v[1] * wall_to_one
        v[0] *= -1
    else:
        # 两球相撞
        p[0] += v[0] * one_to_two
        p[1] += v[1] * one_to_two
        total_mass = m[0] + m[1]
        v0_new = (m[0] - m[1])/total_mass * v[0] + 2*m[1]/total_mass * v[1]
        v1_new = 2*m[0]/total_mass * v[0] + (m[1] - m[0])/total_mass * v[1]
        v = [v0_new, v1_new]

# 输出结果
print(f"π: {collisions}")

内容的提问来源于stack exchange,提问作者meowdog011011

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 06:05:54