
import math import time import tkinter as tk from tkinter import messagebox, ttk from concurrent.futures import ThreadPoolExecutor, Future from typing import List def is_prime(n): """ 判断一个数是否为素数 """ if n < 2: return False elif n == 2: return True elif n % 2 == 0: return False else: for i in range(3, int(math.sqrt(n))+1, 2): if n % i == 0: return False return True def factorization(n): """ 分解质因数 """ factors = [] for i in range(2, int(math.sqrt(n))+1): while n % i == 0: factors.append(i) n //= i if n == 1: break if n > 1: factors.append(n) return factors def calculate(): try: n = int(entry.get()) except ValueError: messagebox.showerror("错误", "请输入一个整数") return progress_bar['value'] = 0 result.set("计算中,请稍候...") future = executor.submit(calculate_result, n) future.add_done_callback(on_calculate_done) # 启动进度条更新线程 progress_future = executor.submit(progress_worker, future) def calculate_result(n): start_time = time.time() if is_prime(n): result_str = f"{n} 是素数" else: factors = factorization(n) result_str = f"{n} 不是素数,它可以分解为 {factors}" end_time = time.time() result_str += f" 用时 {end_time - start_time:.2f} 秒" return result_str def on_calculate_done(future: Future): result.set(future.result()) def quit_program(): root.quit() def update_progress(progress): progress_bar['value'] = progress def progress_worker(future: Future): start_time = time.time() while not future.done(): elapsed_time = time.time() - start_time progress = elapsed_time / progress_bar_max_time * 100 progress = min(progress, 100) update_progress(progress) time.sleep(0.1) updae_progress(100) root = tk.Tk() root.title("素数判断") # 创建控件 label = ttk.Label(root, text="请输入一个整数:") label.pack(pady=10) entry = ttk.Entry(root, width=40) entry.pack(pady=10) progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=400, mode='determinate') progress_bar.pack(pady=10) button = ttk.Button(root, text="判断", command=calculate) button.pack(pady=10) result = tk.StringVar() result.set("结果将显示在这里") result_label = ttk.Label(root, textvariable=result) result_label.pack(pady=10) quit_button = ttk.Button(root, text="退出", command=quit_program) quit_button.pack(pady=10) # 设置布局 root.geometry("500x300") executor = ThreadPoolExecutor(max_workers=2) # 增加线程池大小为 2 ,用于同时执行计算和进度条更新任务 progress_bar_max_time = 5 # 进度条走满需要的时间,单位为秒 def calculate(): try: n = int(entry.get()) except ValueError: messagebox.showerror("错误", "请输入一个整数") return progress_bar['value'] = 0 result.set("计算中,请稍候...") future = executor.submit(calculate_result, n) future.add_done_callback(on_calculate_done) progress_future = executor.submit(progress_worker, future) def on_calculate_done(future: Future): result.set(future.result()) progress_bar['value'] = 100 future.cancel() # 计算完成,取消进度条更新任务 def update_progress(progress): progress_bar['value'] = progress def progress_worker(future: Future): start_time = time.time() while not future.done(): elapsed_time = time.time() - start_time progress = elapsed_time / progress_bar_max_time * 100 progress = min(progress, 100) update_progress(progress) time.sleep(0.1) update_progress(100) root.mainloop() 这个是让 ChatGPT 写的判断素数的代码,使用 Python 3.11.2 版本 执行,但是进度条不管怎么改都不完美。 之前 GUI 界面上没进度条的,命令行窗口里有,很准确,还有倒计时、百分比等信息, 移到 GUI 界面上就一直不完美,要么点了判断,进度条不走,出结果的时候一下子拉满;要么进度条走完了还在计算中,代码里用 progress_bar_max_time = 5 的固定值不咋地,弄个预估的动态值也行啊,ChatGPT 也知道我的意思,就是弄不出来。
我要求就是点判断后进度条开始匀速走,走完了刚好出来结果,最好进度条右边放个动态百分比数字。 放进度条就是为了计算大一点数时直观感受到大概时间
1 Devilker 2023-03-21 07:41:23 +08:00 1999 除以 3 那个吗 哈哈哈哈 |
2 Rever4433 2023-03-21 10:45:36 +08:00 这种进度条确实很难完美实现,举个例子,2147483647000007 和 214748364700007 ,在我的 i5 7300hq 的笔记本上前者 5.48s ,后者 0.74s 。并且素数的计算时间要更快。这就使得对于任何一次输入,计算时间都是不确定的。 |
3 guanjinman2022 OP @Rever4433 我知道时间是不确定的。后来让 ChatGPT 引入预估时间函数,用这个预估时间替换那个 5 来赋值。结果还是不行,点判断后进度条不走,显示计算中,相当于先后台计算一遍,知道时间后,再走进度条,走完刚好出来时间,整个过程相当于 2 倍时间。 |
4 lmshl 2023-03-21 16:34:02 +08:00 这属于问题定义不清,gpt 也帮不了你了 让我做的话我可能会这样,告诉 gpt 用 MillerRabin 算法实现一个素性检验算法,设定一个足够大的阈值,比如实验 20 次以后就认定输入是素数,因为伪素数几率已经足够低到可以忽略了。 然后画进度条不过就是试验次数这一固定数值,你甚至不需要进度条,眨眼就验证完了。 |