test_ai.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import math
  2. import tkinter as tk
  3. from tkinter import messagebox, ttk
  4. from decimal import Decimal, getcontext
  5. import threading
  6. # 定义 Chudnovsky 算法计算圆周率的函数
  7. def compute_pi_chudnovsky(iterations, progress_callback):
  8. # 设置 Decimal 精度,确保足够的有效数字
  9. getcontext().prec = 250 # 设置更高的精度,确保中间计算的准确性
  10. # 初始化常量
  11. C = Decimal(426880) * Decimal(10005).sqrt()
  12. M = Decimal(1)
  13. L = Decimal(13591409)
  14. X = Decimal(-262537412640768000) # 初始 X
  15. K = Decimal(6)
  16. S = Decimal(L)
  17. total_iterations = iterations
  18. for i in range(1, total_iterations + 1): # 从 1 开始迭代
  19. if i % 10 == 0:
  20. progress_callback((i / total_iterations) * 100)
  21. # 计算 M 和 L
  22. M = (K**3 - 16 * K) * M // Decimal(i**3)
  23. L += Decimal(545140134)
  24. # 计算 S
  25. try:
  26. S += M * L / X
  27. except ZeroDivisionError as e:
  28. raise ValueError(f"除零错误在迭代次数: {i}, X: {X}, M: {M}, L: {L}") from e
  29. except Exception as e:
  30. raise ValueError(f"其他错误在迭代次数: {i}, X: {X}, M: {M}, L: {L}, S: {S}") from e
  31. # 更新 X 和 K
  32. X *= Decimal(-262537412640768000)
  33. K += Decimal(12)
  34. pi = C / S
  35. return +pi # 返回正数值
  36. # 定义工作线程函数,用于在后台计算圆周率
  37. def worker(iterations, progress_callback, result_callback):
  38. try:
  39. pi_computed = compute_pi_chudnovsky(iterations, progress_callback)
  40. result_callback(pi_computed)
  41. except Exception as e:
  42. result_callback(None, str(e))
  43. # 定义计算按钮点击事件处理函数
  44. def on_calculate():
  45. try:
  46. iterations = int(entry_iterations.get())
  47. if iterations < 1:
  48. raise ValueError("迭代次数必须大于0")
  49. # 创建进度窗口
  50. progress_window = tk.Toplevel(root)
  51. progress_window.title("计算进度")
  52. # 初始化进度条变量
  53. progress_var = tk.DoubleVar()
  54. # 创建进度条控件
  55. progress = ttk.Progressbar(progress_window, variable=progress_var, maximum=100)
  56. progress.pack(pady=20, padx=20, fill='x')
  57. # 创建进度标签控件
  58. progress_label = tk.Label(progress_window, text="0%")
  59. progress_label.pack(pady=10)
  60. def progress_callback(progress):
  61. progress_var.set(progress)
  62. progress_label.config(text=f"{int(progress)}%")
  63. progress_window.update_idletasks()
  64. # 定义结果回调函数
  65. def result_callback(pi_computed, error=None):
  66. progress_window.destroy()
  67. if error:
  68. messagebox.showerror("错误", error)
  69. else:
  70. # 获取数学库中的 π 值(这里使用 Decimal 包装)
  71. pi_math = Decimal(str(math.pi))
  72. # 计算误差
  73. difference = abs(pi_computed - pi_math)
  74. # 格式化显示计算结果和数学库中的 π 值,并用科学计数法显示误差
  75. pi_computed_str = f"{pi_computed:.200f}".rstrip('0').rstrip('.')
  76. pi_math_str = f"{pi_math:.200f}".rstrip('0').rstrip('.')
  77. difference_str = f"{difference:.20e}"
  78. message = (f"计算得到的π: {pi_computed_str}\n"
  79. f"数学库中的π: {pi_math_str}\n"
  80. f"差异: {difference_str}")
  81. messagebox.showinfo("结果", message)
  82. # 创建并启动线程进行计算
  83. thread = threading.Thread(target=worker, args=(iterations, progress_callback, result_callback))
  84. thread.start()
  85. except ValueError as e:
  86. messagebox.showerror("错误", str(e))
  87. # 创建主窗口
  88. root = tk.Tk()
  89. root.title("计算圆周率")
  90. # 创建标签和输入框
  91. label_iterations = tk.Label(root, text="迭代次数:")
  92. label_iterations.grid(row=0, column=0, padx=10, pady=10)
  93. entry_iterations = tk.Entry(root)
  94. entry_iterations.grid(row=0, column=1, padx=10, pady=10)
  95. # 创建计算按钮
  96. button_calculate = tk.Button(root, text="计算", command=on_calculate)
  97. button_calculate.grid(row=1, column=0, columnspan=2, pady=10)
  98. # 运行主循环
  99. root.mainloop()