计算圆周率PI
import math
from decimal import Decimal, getcontext
import time
from tqdm import tqdm
from alive_progress import alive_bar
import sys
def compute_pi_chudnovsky(precision, progress_bar_type="tqdm"):
"""
使用Chudnovsky算法计算π到指定精度
参数:
precision: 要计算的小数位数
progress_bar_type: 进度条类型("tqdm", "alive", "simple")
返回:
π的Decimal值
"""
# 设置Decimal的精度
getcontext().prec = precision + 2 # 多加2位保证精度
C = Decimal(426880) * Decimal(10005).sqrt()
M = Decimal(1)
L = Decimal(13591409)
X = Decimal(1)
K = Decimal(6)
S = Decimal(0)
# 计算需要的迭代次数
terms = (precision // 14) + 1
# 选择进度条类型
if progress_bar_type == "tqdm":
iterator = tqdm(range(terms), desc="计算π", unit="项")
elif progress_bar_type == "alive":
with alive_bar(terms, title="计算π") as bar:
for k in range(terms):
# 计算当前项
S += M * L / X
# 更新各项
L += 545140134
X *= -262537412640768000
M = M * (K**3 - 16*K) / (k+1)**3
K += 12
bar()
pi = C / S
elif progress_bar_type == "simple":
for k in range(terms):
# 计算当前项
S += M * L / X
# 更新各项
L += 545140134
X *= -262537412640768000
M = M * (K**3 - 16*K) / (k+1)**3
K += 12
# 简单进度条
progress = (k + 1) / terms
bar_length = 50
block = int(round(bar_length * progress))
text = "\r计算π: [{0}] {1:.1f}%".format("#" * block + "-" * (bar_length - block), progress * 100)
sys.stdout.write(text)
sys.stdout.flush()
time.sleep(0.01)
pi = C / S
print() # 换行
else:
for k in range(terms):
S += M * L / X
L += 545140134
X *= -262537412640768000
M = M * (K**3 - 16*K) / (k+1)**3
K += 12
pi = C / S
return pi
def main():
print("圆周率π高精度计算器")
print("====================")
try:
precision = int(input("请输入要计算的小数位数(建议100-10000): "))
if precision < 1:
raise ValueError
print("\n选择进度条类型:")
print("1. tqdm进度条(推荐)")
print("2. alive-progress动态进度条")
print("3. 简单文本进度条")
print("4. 无进度条")
choice = input("请选择(1-4): ")
start_time = time.time()
if choice == "1":
pi = compute_pi_chudnovsky(precision, "tqdm")
elif choice == "2":
pi = compute_pi_chudnovsky(precision, "alive")
elif choice == "3":
pi = compute_pi_chudnovsky(precision, "simple")
else:
pi = compute_pi_chudnovsky(precision, "none")
end_time = time.time()
print("\n计算完成!")
print(f"耗时: {end_time - start_time:.2f}秒")
# 输出结果(只显示前100位,避免控制台输出过长)
pi_str = str(pi)
print(f"\nπ的前{min(100, precision)}位:")
print(pi_str[:min(102, precision + 2)]) # 加2是因为"3."开头
# 询问是否保存到文件
save = input("\n是否保存完整结果到文件?(y/n): ").lower()
if save == "y":
filename = f"pi_{precision}digits.txt"
with open(filename, "w") as f:
f.write(pi_str)
print(f"结果已保存到{filename}")
except ValueError:
print("错误: 请输入一个正整数!")
except KeyboardInterrupt:
print("\n计算被用户中断")
except Exception as e:
print(f"发生错误: {str(e)}")
if name == "main":
# 检查并安装必要的库
try:
from tqdm import tqdm
except ImportError:
print("正在安装tqdm库...")
import subprocess
subprocess.run(["pip", "install", "tqdm"], check=True)
try:
from alive_progress import alive_bar
except ImportError:
print("正在安装alive-progress库...")
import subprocess
subprocess.run(["pip", "install", "alive-progress"], check=True)
main()