我正在编写一个科学计算器作为项目的一部分,但是当我单击“=”符号时,6 个函数(coth、acot、sec、sech、asec 和 acsc)在计算字段中显示错误消息,而不是结果。其余部分以弧度显示正确的结果。我只能使用数学模块,因此我尝试使用其他正在运行的函数的反转来创建给定函数的等效项。不幸的是,这个解决方案只在我的案例中工作了 1/3 的时间。我附上一个包含三角学、数字和基本数学运算的代码片段。
import tkinter as tk
import math
class ScientificCalculator:
def __init__(self, root):
self.root = root
root.title("Kalkulator Naukowy")
self.expression = ""
self.max_history_lines = 10
self.memory = 0
self.display = tk.Entry(root, width=40, font=('Arial', 20), borderwidth=5)
self.display.grid(row=0, column=0, columnspan=7, pady=(20, 10))
buttons = [
"7", "8", "9", "+", "sin(", "sinh(", "asin(",
"4", "5", "6", "-", "cos(", "cosh(", "acos(",
"1", "2", "3", "*", "tan(", "tanh(", "atan(",
"0", ".", "(", ")", "=", "AC", "C", "cot(",
"coth(", "acot(", "sec(", "sech(", "asec(", "csc(", "csch(",
"acsc("
]
row_val = 1
col_val = 0
for button in buttons:
if button == "=":
tk.Button(root, text=button, padx=30, pady=20, command=lambda b=button: self.button_click(b), font=('Arial', 14, 'bold'), bg='#082e79', fg='white').grid(row=row_val, column=col_val, columnspan=2, sticky='nsew')
col_val += 2
elif button in ["C", "AC"]:
tk.Button(root, text=button, padx=30, pady=20, command=lambda b=button: self.button_click(b), font=('Arial', 14, 'bold'), bg='#082e79', fg='white').grid(row=row_val, column=col_val, columnspan=2, sticky='nsew')
col_val += 2
else:
tk.Button(root, text=button, padx=20, pady=20, command=lambda b=button: self.button_click(b), font=('Arial', 14, 'bold'), bg='#666666', fg='white').grid(row=row_val, column=col_val, padx=1, pady=1, sticky='nsew')
col_val += 1
if col_val > 6:
col_val = 0
row_val += 1
self.history_text = tk.Text(root, height=10, width=40)
self.history_text.grid(row=10, column=0, columnspan=7, padx=2, pady=2, sticky='nsew')
self.history = []
def button_click(self, button):
if button == "=":
try:
self.expression = self.expression.replace("cot(", "1/math.tan(")
self.expression = self.expression.replace("coth(", "1/math.tanh(")
self.expression = self.expression.replace("acot(", "1/math.atan(")
self.expression = self.expression.replace("sec(", "1/math.cos(")
self.expression = self.expression.replace("sech(", "1/math.cosh(")
self.expression = self.expression.replace("asec(", "1/math.acos(")
self.expression = self.expression.replace("csc(", "1/math.sin(")
self.expression = self.expression.replace("csch(", "1/math.sinh(")
self.expression = self.expression.replace("acsc(", "1/math.asin(")
result = str(eval(self.expression))
history_expression = self.expression
self.history.insert(0, history_expression + " = " + result)
self.display.delete(0, tk.END)
self.display.insert(0, result)
self.update_history()
self.expression = result
except Exception:
self.display.delete(0, tk.END)
self.display.insert(0, "Błąd")
elif button == "C":
self.expression = ""
self.display.delete(0, tk.END)
elif button == "AC":
self.memory = 0
self.expression = ""
self.display.delete(0, tk.END)
self.history = []
self.update_history()
else:
if button in ["sin(", "cos(", "tan(", "sinh(", "cosh(", "tanh(", "asin(", "acos(", "atan("]:
self.expression += "math." + button
else:
self.expression += button
self.display.insert(tk.END, button)
def update_history(self):
if len(self.history) > self.max_history_lines:
self.history = self.history[:self.max_history_lines]
self.history_text.delete(1.0, tk.END)
for item in self.history:
self.history_text.insert(tk.END, item + "\n")
if __name__ == "__main__":
root = tk.Tk()
calc = ScientificCalculator(root)
root.geometry("750x730")
root.configure(bg="#bfbfbf")
root.mainloop()
感谢您的提问,欢迎来到 SO。
解决此问题的第一步是打印更详细的错误消息。 捕捉到
Exception
告诉我们存在 a 问题,而不是正在发生什么问题。
我们可以通过像这样的修改来准确地知道这一点:
# ...
self.expression = result
except Exception as e:
self.display.delete(0, tk.END)
self.display.insert(0, "Błąd")
print("Exception:", e)
# ...
添加此内容并尝试评估 acsc(-0.5),我收到一条错误消息:
Exception: name 'a1' is not defined
该名称
a1
不在给定片段中的任何位置出现,所以让我们深入挖掘一下:
我在
button_click
内添加一行,打印正在评估的确切表达式:
# ...
self.expression = self.expression.replace("acsc(", "1/math.asin(")
print("Expression before eval:",self.expression)
result = str(eval(self.expression))
# ...
使用相同的输入再次运行代码,问题立即变得清晰:
Expression before eval: a1/math.sin(5)
Exception: name 'a1' is not defined
acsc(-0.5)
应该变成 1/math.asin(-0.5)
。相反,它变成了a1/math.sin(-0.5)
。这是我们最终解决问题所需要的提示。让我们看一下应该进行替换的代码部分:
# ...
self.expression = self.expression.replace("csc(", "1/math.sin(")
self.expression = self.expression.replace("csch(", "1/math.sinh(")
self.expression = self.expression.replace("acsc(", "1/math.asin(")
Python 从上到下执行事物。第一次替换发生在最后一次替换之前。
因此,
csc(-0.5)
中的acsc(-0.5)
部分被替换,其余替换不执行任何操作。
我们终于可以通过改变顺序来解决问题了。
self.expression = self.expression.replace("acot(", "1/math.atan(")
self.expression = self.expression.replace("cot(", "1/math.tan(")
self.expression = self.expression.replace("coth(", "1/math.tanh(")
self.expression = self.expression.replace("asec(", "1/math.acos(")
self.expression = self.expression.replace("sec(", "1/math.cos(")
self.expression = self.expression.replace("sech(", "1/math.cosh(")
self.expression = self.expression.replace("acsc(", "1/math.asin(")
self.expression = self.expression.replace("csc(", "1/math.sin(")
self.expression = self.expression.replace("csch(", "1/math.sinh(")
进行此更改,当我在新程序中输入 acsc(-0.5) 时,我得到的值为
-1.9098593171027438
,这是正确且预期的输出。
我希望这有助于您了解您所面临的问题以及将来如何解决问题。