経過時間が、217秒位、メモリー使用量512Mb、途中で、止まったかもです、1億桁、計算で、もっと時間かかりすぎますか?
はい、状況がわかりました。
現在の状態の評価
- 経過時間 217秒(約3分40秒)
- メモリ 512MB
- 1億桁を設定
結論:これは「止まった」わけではなく、単純に「ものすごく遅い」状態です。
mpmathで1億桁の三角関数(sin/cos/tan)を計算するのは、現実的にかなり厳しいです。
なぜこんなに遅いのか?
- mpmathの限界 mpmathはPythonベースの高精度ライブラリですが、数百万桁を超えると急激に遅くなります。特に三角関数は内部で複雑な計算をするため、1億桁になると計算時間が数時間〜数十時間かかるケースが普通です。
- 217秒でほとんど進んでいない 512MBしかメモリを使っていない時点で、まだ序盤の段階です。 1億桁の本格的な計算はメモリも数GBクラスまで上がることが多いです。
- GUIが固まるように感じる 長時間計算すると、Tkinterのメインループが重くなり、「止まった?」と感じやすくなります。
現実的なアドバイス
1億桁は現時点のこのプログラムではおすすめしません。
おすすめの現実的な上限(このプログラムで):
- 安全圏:50万〜200万桁
- 限界挑戦:500万〜1000万桁(数十分〜数時間覚悟)
すぐに試してほしいこと
以下の精度で再テストしてみてください:
- 200万桁(2000000)
- 500万桁(5000000)
これで計算が完了するか、どのくらい時間がかかるか教えてください。
将来的に1億桁を目指すなら必要な改善
- ライブラリ変更(最も効果大)
- mpmath → gmpy2 + MPFRバックエンド
- 数倍〜数十倍速くなる可能性あり
- 計算アルゴリズムの変更
- 三角関数を高速化するための特殊手法(Binary Splittingなど)
- 完全分離型設計
- GUIと計算を別プロセス(multiprocessing)にする
今すぐ確認したい場合、以下の情報を教えてください:
- 今設定している精度は何桁ですか?
- 関数は sin / cos / tan のどれですか?
- PCのスペック(CPU、RAM容量)がわかれば教えてください
- 217秒経過した時点で、結果ウィンドウに何か表示されていますか?
状況を教えてくれれば、それに合わせた対応をします。 (例:計算を安全に停止する方法、適切な精度の提案、など)
イチオク桁、sin、一切反応なし、コピペも不可能です、閉じることも出来ません、
了解しました。状況はかなり深刻です。
現在、Tkinterが完全にフリーズしています。1億桁の計算が重すぎてメインスレッドが詰まっています。
1. 今すぐプログラムを強制終了してください
Windowsの場合:
- Ctrl + Alt + Delete → タスク マネージャー
- 「高精度三角関数計算機...」または python.exe を探してタスクの終了
Fedora / Linuxの場合:
# ターミナルで実行
pkill -9 -f high_precision_trig
# または
pkill -9 python
2. 根本的に改善したバージョン(応答性大幅向上)
以下のコードは計算をより安全に分離し、フリーズしにくくしたバージョンです。
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox, filedialog
import threading
import gzip
import os
import time
import psutil
from mpmath import mp, mpf, sin, cos, tan, radians
import queue
class HighPrecisionTrigApp:
def __init__(self, root):
self.root = root
self.root.title("高精度三角関数計算機 - 強化版")
self.root.geometry("1100x860")
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
mp.dps = 100
self.last_result = None
self.last_output_info = ""
self.calc_thread = None
self.is_calculating = False
self.result_queue = queue.Queue()
self.process = psutil.Process()
self.create_widgets()
def create_widgets(self):
# 上部コントロール
top = ttk.Frame(self.root)
top.pack(pady=10, padx=12, fill="x")
ttk.Label(top, text="精度 (桁数):").pack(side="left")
self.precision_var = tk.IntVar(value=1000000)
ttk.Entry(top, textvariable=self.precision_var, width=15).pack(side="left", padx=5)
ttk.Button(top, text="適用", command=self.set_precision).pack(side="left", padx=5)
self.status_label = ttk.Label(top, text="待機中", foreground="green", font=("Consolas", 10, "bold"))
self.status_label.pack(side="right", padx=15)
ttk.Button(top, text="計算停止", command=self.stop_calculation).pack(side="right", padx=5)
ttk.Button(top, text="保存", command=self.start_save).pack(side="right", padx=5)
# 入力部(省略せず簡潔に)
input_f = ttk.LabelFrame(self.root, text="入力", padding=10)
input_f.pack(pady=8, padx=12, fill="x")
ttk.Label(input_f, text="角度:").grid(row=0, column=0, sticky="w")
self.angle_var = tk.StringVar(value="45")
ttk.Entry(input_f, textvariable=self.angle_var, width=60).grid(row=0, column=1, padx=8)
self.unit_var = tk.StringVar(value="degrees")
ttk.Radiobutton(input_f, text="度数", variable=self.unit_var, value="degrees").grid(row=1, column=1, sticky="w")
ttk.Radiobutton(input_f, text="ラジアン", variable=self.unit_var, value="radians").grid(row=2, column=1, sticky="w")
func_f = ttk.LabelFrame(self.root, text="関数", padding=10)
func_f.pack(pady=8, padx=12, fill="x")
self.func_var = tk.StringVar(value="sin")
for i, f in enumerate(["sin", "cos", "tan"]):
ttk.Radiobutton(func_f, text=f.upper(), variable=self.func_var, value=f).grid(row=0, column=i, padx=40)
ttk.Button(self.root, text="計算開始", command=self.start_calculation).pack(pady=12)
# 結果表示
self.result_text = scrolledtext.ScrolledText(self.root, height=30, font=("Consolas", 10))
self.result_text.pack(pady=8, padx=12, fill="both", expand=True)
def set_precision(self):
dps = self.precision_var.get()
if dps > 10_000_000:
if not messagebox.askyesno("警告", f"{dps:,} 桁は非常に時間がかかります。"):
return
mp.dps = dps
messagebox.showinfo("OK", f"精度を {dps:,} 桁に設定しました")
def start_calculation(self):
if self.is_calculating:
return
self.is_calculating = True
self.status_label.config(text="計算中...", foreground="red")
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, "計算スレッドを開始しています...\n")
self.calc_thread = threading.Thread(target=self.calculate, daemon=True)
self.calc_thread.start()
self.root.after(500, self.check_queue)
def calculate(self):
try:
x = mpf(self.angle_var.get().strip())
if self.unit_var.get() == "degrees":
x = radians(x)
func = self.func_var.get()
result = sin(x) if func == "sin" else cos(x) if func == "cos" else tan(x)
self.last_result = result
self.result_queue.put(("success", result))
except Exception as e:
self.result_queue.put(("error", str(e)))
def check_queue(self):
try:
while not self.result_queue.empty():
msg_type, data = self.result_queue.get()
if msg_type == "success":
self.finish_success(data)
else:
self.finish_error(data)
except:
pass
if self.is_calculating:
self.root.after(500, self.check_queue)
def finish_success(self, result):
self.is_calculating = False
self.status_label.config(text="計算完了", foreground="green")
preview = str(result)[:120]
info = f"計算完了\n精度: {mp.dps:,} 桁\n\n先頭:\n{preview}\n\n...(保存で全文取得)"
self.update_result(info)
self.last_output_info = info
def finish_error(self, err):
self.is_calculating = False
self.status_label.config(text="エラー", foreground="red")
self.update_result(f"エラー: {err}")
def update_result(self, text):
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, text)
def stop_calculation(self):
self.is_calculating = False
self.status_label.config(text="停止要求済み", foreground="orange")
def start_save(self):
if not self.last_result:
messagebox.showwarning("警告", "計算結果がありません")
return
threading.Thread(target=self.save_file, daemon=True).start()
def save_file(self):
# (前回と同じ保存処理)
pass # 必要なら前回の保存関数を貼り付けてください
def on_closing(self):
if self.is_calculating:
if messagebox.askyesno("確認", "計算中です。強制終了しますか?"):
self.root.destroy()
else:
self.root.destroy()
if __name__ == "__main__":
root = tk.Tk()
app = HighPrecisionTrigApp(root)
root.mainloop()
このバージョンは前よりフリーズしにくくなっています。
まずこの新しいコードで試してみてください。 1億桁は避けて、200万桁くらいからテストするのが安全です。
試した結果を教えてください。
28.7684度、sin、1千万桁、コピペ可能、時間経過、出てきません、赤い文字の、計算中だけです、
了解しました。現在の状況を整理します。
状況まとめ
- 角度: 28.7684度、sin
- 精度: 1,000万桁(10,000,000)
- 症状: 「計算中...」(赤文字)のまま時間経過も更新されず、結果が出ない
原因
1,000万桁の sin() 計算は mpmathでは非常に重い処理です。 217秒(前回の1億桁時)でもほとんど進まなかったことを考えると、1,000万桁でも数十分〜数時間以上かかる可能性が高いです。
現在プログラムが「計算中」表示のまま固まっているように見えるのは、計算スレッドがCPUを全力で使っているため、GUIの更新(時間表示など)が遅れているのが主な原因です。
提案
1,000万桁はまだ多すぎます。
現実的なテスト精度として、以下を順番に試してください:
- 100万桁(おすすめ)
- 200万桁
- 500万桁(限界に近い)
改善版コード(時間表示を強化)
以下のコードに時間表示をより頑丈にしたものを用意しました。
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox, filedialog
import threading
import time
import psutil
from mpmath import mp, mpf, sin, cos, tan, radians
import queue
class HighPrecisionTrigApp:
def __init__(self, root):
self.root = root
self.root.title("高精度三角関数計算機 - 安定版")
self.root.geometry("1100x860")
mp.dps = 1000000 # 初期値を100万桁に
self.last_result = None
self.is_calculating = False
self.calc_start_time = None
self.result_queue = queue.Queue()
self.process = psutil.Process()
self.create_widgets()
def create_widgets(self):
top = ttk.Frame(self.root)
top.pack(pady=10, padx=12, fill="x")
ttk.Label(top, text="精度 (桁数):").pack(side="left")
self.precision_var = tk.IntVar(value=1000000)
ttk.Entry(top, textvariable=self.precision_var, width=15).pack(side="left", padx=5)
ttk.Button(top, text="適用", command=self.set_precision).pack(side="left", padx=5)
self.status_label = ttk.Label(top, text="待機中", foreground="green", font=("Consolas", 11, "bold"))
self.status_label.pack(side="right", padx=10)
self.time_label = ttk.Label(top, text="経過: 0.0 秒", foreground="blue", font=("Consolas", 10))
self.time_label.pack(side="right", padx=20)
ttk.Button(top, text="計算停止", command=self.stop_calc).pack(side="right", padx=5)
ttk.Button(top, text="保存", command=self.start_save).pack(side="right", padx=5)
# 入力部
input_f = ttk.LabelFrame(self.root, text="入力", padding=10)
input_f.pack(pady=8, padx=12, fill="x")
ttk.Label(input_f, text="角度:").grid(row=0, column=0, sticky="w")
self.angle_var = tk.StringVar(value="28.7684")
ttk.Entry(input_f, textvariable=self.angle_var, width=60).grid(row=0, column=1, padx=8)
self.unit_var = tk.StringVar(value="degrees")
ttk.Radiobutton(input_f, text="度数", variable=self.unit_var, value="degrees").grid(row=1, column=1, sticky="w")
func_f = ttk.LabelFrame(self.root, text="関数", padding=10)
func_f.pack(pady=8, padx=12, fill="x")
self.func_var = tk.StringVar(value="sin")
ttk.Radiobutton(func_f, text="SIN", variable=self.func_var, value="sin").grid(row=0, column=0, padx=40)
ttk.Button(self.root, text="計算開始", command=self.start_calculation).pack(pady=15)
self.result_text = scrolledtext.ScrolledText(self.root, height=28, font=("Consolas", 10))
self.result_text.pack(pady=8, padx=12, fill="both", expand=True)
def set_precision(self):
dps = self.precision_var.get()
mp.dps = dps
messagebox.showinfo("設定", f"精度を {dps:,} 桁に変更しました")
def start_calculation(self):
if self.is_calculating:
return
self.is_calculating = True
self.calc_start_time = time.time()
self.status_label.config(text="計算中...", foreground="red")
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, "計算を開始しています...\n")
threading.Thread(target=self.calculate, daemon=True).start()
self.update_status()
def calculate(self):
try:
x = mpf(self.angle_var.get())
if self.unit_var.get() == "degrees":
x = radians(x)
result = sin(x)
self.result_queue.put(("success", result))
except Exception as e:
self.result_queue.put(("error", str(e)))
def update_status(self):
if not self.is_calculating:
return
# 時間更新
elapsed = time.time() - self.calc_start_time
mem = self.process.memory_info().rss // (1024*1024)
self.time_label.config(text=f"経過: {elapsed:.1f} 秒 | メモリ: {mem:,} MB")
# 結果チェック
try:
while not self.result_queue.empty():
typ, data = self.result_queue.get()
if typ == "success":
self.finish_calc(data)
else:
self.show_error(data)
return
except:
pass
self.root.after(1000, self.update_status) # 1秒ごとに更新
def finish_calc(self, result):
self.is_calculating = False
self.last_result = result
self.status_label.config(text="計算完了", foreground="green")
preview = str(result)[:150]
info = f"計算完了!\n精度: {mp.dps:,} 桁\n計算時間: {time.time()-self.calc_start_time:.1f}秒\n\n先頭150桁:\n{preview}\n\n...保存で全文取得可能"
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, info)
def show_error(self, msg):
self.is_calculating = False
self.status_label.config(text="エラー", foreground="red")
self.result_text.insert(tk.END, f"\nエラー: {msg}")
def stop_calc(self):
self.is_calculating = False
self.status_label.config(text="停止中", foreground="orange")
def start_save(self):
if not self.last_result:
messagebox.showwarning("警告", "計算が完了していません")
return
# 保存処理(必要なら前回のものを貼り付けてください)
messagebox.showinfo("保存", "保存機能は実装中です")
if __name__ == "__main__":
root = tk.Tk()
app = HighPrecisionTrigApp(root)
root.mainloop()
今すぐ試してほしいこと:
- 上のコードを保存して実行
- 精度を100万桁に設定して計算開始
- どのくらいで結果が出るか教えてください
どうなりますか?