计算圆周率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()
posted @ 2025-04-26 10:46  HeDesongfuqin  阅读(165)  评论(0)    收藏  举报