| 
 | 
 
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册  
 
x
 
上期作品 
 
熟悉我的都知道啊,这计算器已经迭代多次了。不浪费大家时间,只放一个上次的,有兴趣可以看看 
 
0.1+0.2可以等于0.3!全FishC最好的计算器(不是),满足你对计算器的一切幻想 https://fishc.com.cn/thread-245235-1-1.html (出处: 鱼C论坛)]0.1+0.2可以等于0.3!全FishC最好的计算器 
 
 
 
 
 
本期介绍 
 
@isdkz @zhangjinxuan @sfqxx @不二如是 @python爱好者. @ba21 @KeyError @python爱好者. @小甲鱼的三师弟 @~风介~ @小甲鱼的二师兄 @鱼小二 
   
 
可以注意到很多区别 
 
 
全FishC最好的计算器! 
 
    消除误差!0.1+0.2可以等于0.3! 
    过大或过小的数值会用科学计数法 
    任选角度测量制度(默认角度制) 
    注意: 
    阶乘 ! 是括号之下优先级最高的运算 
    算术平方根运算后不加括号将只算数字 
    小数点后取7位(可调整),采用银行家舍入 
    【四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一】 
    支持鼠标点击和键盘输入(非常神奇),但尽量不要混合使用 
    其中键盘输入 删除,回车,C有奇效。 
    输入0b, 0o, 0x前缀后回车或点击“=”可以转换为十进制。计算的十进制结果可直接转换进制 
    还支持某些(奇怪)运算,如:√√√√65536(就是2),3!!(720) 
    甚至还可以动态调整运算精度 
 
 
完整代码 
 
- """frame框架布局
 
 -     在frame内部,可以重新进行一次布局"""
 
 - import ttkbootstrap as ttk
 
 - from tkinter.messagebox import showinfo
 
 - from PIL import ImageTk, Image
 
 - from decimal import Decimal
 
 - from math import sqrt, sin, cos, tan, pi, radians, factorial
 
  
- use_big = True
 
 - angle_set = "角度制"
 
 - digits_after_point = 7
 
  
 
- def resize_window():
 
 -     global use_big
 
 -     step = 0
 
  
-     def worker(u_big):
 
 -         nonlocal step
 
 -         if u_big:
 
 -             win.geometry(f"{432-step}x344")
 
 -             step += 24
 
 -             if step == 72:
 
 -                 btnEqual.grid(row=ri + 1, column=0, columnspan=5, sticky=ttk.EW)
 
 -             elif step == 144:
 
 -                 btnEqual.grid(row=ri + 1, column=0, columnspan=4, sticky=ttk.EW)
 
 -             if step <= 144:
 
 -                 print(step)
 
 -                 win.after(20, worker, u_big)
 
 -         else:
 
 -             win.geometry(f"{288 + step}x344")
 
 -             step += 24
 
 -             if step == 72:
 
 -                 btnEqual.grid(row=ri + 1, column=0, columnspan=5, sticky=ttk.EW)
 
 -             elif step == 144:
 
 -                 btnEqual.grid(row=ri + 1, column=0, columnspan=6, sticky=ttk.EW)
 
 -             if step <= 144:
 
 -                 print(step)
 
 -                 win.after(20, worker, u_big)
 
 -     worker(use_big)
 
 -     use_big = not use_big
 
  
 
- def like_ago():
 
 -     global angle_set, digits_after_point
 
 -     angle_set = "角度制"
 
 -     digits_after_point = 7
 
  
 
- def top1():
 
 -     top = ttk.Toplevel(title="详情")
 
 -     label = ttk.Label(master=top, text="""
 
 -     全FishC最好的计算器!
 
 -     
 
 -     消除误差!0.1+0.2可以等于0.3!
 
 -     过大或过小的数值会用科学计数法
 
 -     任选角度测量制度(默认角度制)
 
 -     注意:
 
 -     阶乘 ! 是括号之下优先级最高的运算
 
 -     算术平方根运算后不加括号将只算数字
 
 -     小数点后取7位(可调整),采用银行家舍入
 
 -     【四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一】
 
 -     支持鼠标点击和键盘输入(非常神奇),但尽量不要混合使用
 
 -     其中键盘输入 删除,回车,C有奇效。
 
 -     输入0b, 0o, 0x前缀后回车或点击“=”可以转换为十进制。计算的十进制结果可直接转换进制
 
 -     还支持某些(奇怪)运算,如:√√√√65536(就是2),3!!(720)
 
 -     甚至还可以动态调整运算精度
 
 -                                        """,
 
 -                       font=("楷体", 14))
 
 -     label.pack()
 
  
 
- def top2():
 
 -     top = ttk.Toplevel(title="作者")
 
 -     label = ttk.Label(master=top,
 
 -                       text="""作者:FishC 某一个“天”
 
 -                                   ~谢谢使用~""",
 
 -                       font=14)
 
 -     label.pack()
 
  
 
- def top3():
 
 -     top = ttk.Toplevel(title="历史记录")
 
 -     label = ttk.Label(master=top, text="".join(history_input_list), font=("微软雅黑", 12))
 
 -     label.pack()
 
  
 
- def top4():
 
 -     def write_change():
 
 -         history_input_list.append(f"记录!角度测量制度是<{rVar.get()}>\n")
 
 -         history_input_list.append(f"记录!小数点后取<{digits_after_point}>位\n")
 
 -         top.destroy()
 
  
-     def digits_changed(x):
 
 -         global digits_after_point
 
  
-         digits_after_point = int(float(x))
 
 -         print("now222:", digits_after_point)
 
 -         valueVar.set(f"1     小数点后取{digits_after_point}位    15")
 
  
-     def angle_changed():
 
 -         global angle_set
 
 -         angle_set = rVar.get()
 
  
-     top = ttk.Toplevel(title="设置")
 
  
-     global digits_after_point, angle_set
 
 -     valueVar = ttk.StringVar()
 
 -     valueVar.set(f"1     小数点后取{digits_after_point}位    15")
 
 -     l1 = ttk.Label(top, textvariable=valueVar, foreground="green", font=8)
 
 -     l1.pack()
 
 -     sc1 = ttk.Scale(top, length=200, from_=1, to=15, value=digits_after_point, style="TScale",
 
 -                     command=lambda val: digits_changed(val))
 
 -     sc1.pack()
 
  
-     l2 = ttk.Label(top, text="角度测量制度", foreground="purple", font=8)
 
 -     l2.pack(pady=10)
 
 -     rVar = ttk.StringVar()
 
 -     rVar.set(angle_set)  # 开始时选中角度制
 
 -     r1 = ttk.Radiobutton(top, text="角度制", value="角度制", variable=rVar, command=angle_changed)
 
 -     r1.pack()
 
 -     r2 = ttk.Radiobutton(top, text="弧度制", value="弧度制", variable=rVar, command=angle_changed)
 
 -     r2.pack()
 
  
-     l2 = ttk.Label(top, text="*设置无需记录即可生效\n记录后可在历史记录中找到", foreground="red")
 
 -     l2.pack(pady=10)
 
 -     write_btn = ttk.Button(top, text="记录到历史", command=write_change, style="success")
 
 -     write_btn.pack(pady=10)
 
  
 
- win = ttk.Window()
 
 - win.title("FishC最好的?计算器")
 
 - win.geometry("432x364+500+200")
 
 - win.resizable(width=False, height=False)  # 设置不能调整窗口大小
 
 - # 设置窗体图标
 
 - win.iconbitmap("./py_pic/jsq3.ico")
 
 - # 创建菜单栏
 
 - menu_bar = ttk.Menu(win)
 
 - win.config(menu=menu_bar)
 
 - # 创建菜单项
 
 - info_menu = ttk.Menu(menu_bar, tearoff=False)
 
 - info_menu.add_command(label="详情", command=top1)
 
 - info_menu.add_command(label="作者", command=top2)
 
 - menu_bar.add_cascade(label="关于计算器", menu=info_menu)
 
  
- history_menu = ttk.Menu(menu_bar, tearoff=False)
 
 - history_menu.add_command(label="查看", command=top3)
 
 - history_menu.add_command(label="清空", command=lambda: history_input_list.clear())
 
 - menu_bar.add_cascade(label="历史记录", menu=history_menu)
 
  
- system_menu = ttk.Menu(menu_bar, tearoff=False)
 
 - system_menu.add_command(label="转为二进制", command=lambda: showinfo("二进制", f"得数转为二进制是{int(eval(get_result(input_list))):b}"))
 
 - system_menu.add_command(label="转为八进制", command=lambda: showinfo("八进制", f"得数转为八进制是{int(eval(get_result(input_list))):o}"))
 
 - system_menu.add_command(label="转为十六进制", command=lambda: showinfo("十六进制", f"得数转为十六进制是{int(eval(get_result(input_list))):x}"))
 
 - menu_bar.add_cascade(label="整数进制转换", menu=system_menu)
 
  
- control_menu = ttk.Menu(menu_bar, tearoff=False)
 
 - control_menu.add_command(label="调整", command=top4)
 
 - control_menu.add_command(label="恢复默认", command=like_ago)
 
 - control_menu.add_command(label="使用精简版/科学版", command=resize_window)
 
 - menu_bar.add_cascade(label="设置", menu=control_menu)
 
  
- main_style = ttk.Style()
 
 - main_style.configure("TButton", font=("微软雅黑", 15))
 
 - main_style.configure('TScale', sliderlength=30, sliderthickness=20, troughcolor='#D3D3D3', background='#FFFFFF')
 
  
- input_list = []
 
 - history_input_list = []
 
  
 
- def my_factorial(x):
 
 -     try:
 
 -         print("fun:", x)
 
 -         return factorial(int(x))
 
 -     except Exception as e:
 
 -         print(e)
 
 -         varEntry0.set("错误")
 
  
 
- def my_sqrt(x):
 
 -     return Decimal(sqrt(x))
 
  
 
- def my_sin(x):
 
 -     if angle_set == "角度制":
 
 -         angle_in_radians = radians(x)
 
 -         return Decimal(sin(angle_in_radians))
 
 -     else:
 
 -         return Decimal(sin(x))
 
  
 
- def my_cos(x):
 
 -     if angle_set == "角度制":
 
 -         angle_in_radians = radians(x)
 
 -         return Decimal(cos(angle_in_radians))
 
 -     else:
 
 -         return Decimal(cos(x))
 
  
 
- def my_tan(x):
 
 -     if angle_set == "角度制":
 
 -         angle_in_radians = radians(x)
 
 -         return Decimal(tan(angle_in_radians))
 
 -     else:
 
 -         return Decimal(tan(x))
 
  
 
- def calcu(event, is_key=False):
 
 -     global input_list
 
  
-     if varLabel0.get() == "计算过程区:":
 
 -         varLabel0.set("")
 
  
-     def history_separate():
 
 -         history_input_list.append("---------------------------------\n")
 
  
-     def clear():
 
 -         if len(input_list) > 1:  # 除了C之外还有别的
 
 -             history_separate()
 
 -         input_list.clear()
 
 -         varLabel0.set("计算过程区:")
 
 -         varEntry0.set("")
 
  
-     def is_old_entry_part(is_usual=True):
 
 -         global input_list
 
 -         if "=" in varEntry0.get() or "错误" in varEntry0.get():  # 新的算式
 
 -             if is_usual:
 
 -                 history_separate()
 
 -                 input_list = [txt]
 
 -                 varLabel0.set("计算过程区:")
 
 -                 varEntry0.set(txt)
 
 -             else:
 
 -                 varLabel0.set("计算过程区:")
 
 -                 input_list = list(varEntry0.get()[1:])  # 结果部分
 
 -                 varEntry0.set(varEntry0.get()[1:])
 
 -             return False
 
 -         return True
 
  
-     def fast_add(master, text):
 
 -         master.set(master.get() + text)
 
  
-     # 判断输入方式
 
 -     if is_key:
 
 -         txt = event.char
 
 -         print("-------", txt)
 
 -         if txt == "\x08":  # 删除键
 
 -             input_list = input_list[:-1]
 
 -         elif txt == "\r":  # 回车键
 
 -             varLabel0.set("")
 
 -             equal_click()
 
 -         elif txt == "C":  # 清空
 
 -             clear()
 
 -             return "break"  # 取消本次输入
 
 -         elif txt in ("π", "("):
 
 -             try:
 
 -                 if is_old_entry_part():
 
 -                     # 有 IndexError: list index out of range 的危险
 
 -                     if input_list[-2] in ("π", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"):
 
 -                         input_list.append("*")
 
 -                     input_list.append(txt)
 
 -             except Exception as e:
 
 -                 print(e)
 
  
-         else:
 
 -             if len(varEntry0.get()) > 30:
 
 -                 varEntry0.set(varEntry0.get()[:30])
 
 -             else:
 
 -                 if is_old_entry_part():
 
 -                     input_list.append(txt)
 
  
-     else:
 
 -         txt = str(event.widget["text"])
 
  
-         if txt == "取余":
 
 -             txt = "%"
 
 -         elif txt == "整除":
 
 -             txt = "//"
 
 -         elif txt == "x^y":
 
 -             txt = "^"
 
 -         elif txt == "√x":
 
 -             txt = "√"
 
 -         elif txt == "x!":
 
 -             txt = "!"
 
 -         elif txt == "sin x":
 
 -             txt = "sin"
 
 -         elif txt == "cos x":
 
 -             txt = "cos"
 
 -         elif txt == "tan x":
 
 -             txt = "tan"
 
 -         if txt == "+/-":
 
 -             is_old_entry_part(False)
 
 -             if varEntry0.get()[0] == "-":
 
 -                 varEntry0.set(varEntry0.get()[1:])
 
 -                 input_list.reverse()
 
 -                 input_list.remove("-")
 
 -                 input_list.reverse()
 
 -             else:
 
 -                 _ = 0
 
 -                 for i in range(len(varEntry0.get())):
 
 -                     x = varEntry0.get()[i]
 
 -                     if i == 0 and x == "0" and varEntry0.get()[i+1] != ".":
 
 -                         break
 
 -                     elif x == "." or type(eval(x)) == int:
 
 -                         _ -= 1
 
 -                 else:
 
 -                     input_list.insert(_, "-")
 
 -                     varEntry0.set("-" + varEntry0.get())
 
 -         elif txt == "!":
 
 -             only_fact = True
 
 -             _ = 0
 
 -             n = input_list.count(")")
 
 -             x = 0
 
 -             for i in range(len(input_list)):
 
 -                 if input_list[::-1][i] == "(":
 
 -                     _ += 1
 
 -                     if _ == n:
 
 -                         only_fact = False
 
 -                         x = len(input_list) - i - 1
 
 -                         break
 
 -                 elif input_list[::-1][i] in ("+", "-", "*", "/", "%", "//", "^"):
 
 -                     only_fact = False
 
 -                     x = len(input_list) - i
 
 -                     if _ >= n:
 
 -                         break
 
 -             if only_fact:
 
 -                 input_list.insert(0, "!")
 
 -             else:
 
 -                 input_list[x:x] = ["!"]
 
 -         else:
 
 -             input_list.append(txt)
 
  
-         # 防止输入过长
 
 -         if (len(varEntry0.get()) < 26 or txt == "C" or txt == "CE") and txt != "+/-":
 
 -             if txt == "C":  # 清空
 
 -                 clear()
 
  
-             elif txt == "CE":
 
 -                 print("get", varEntry0.get())
 
 -                 if "=" not in varEntry0.get():  # 不能删除得数
 
 -                     input_list.pop()  # 把CE删掉
 
 -                 if varEntry0.get() == "错误":
 
 -                     varEntry0.set("")
 
 -                 elif varEntry0.get():  # 保证输入框有东西
 
 -                     input_list.pop()  # 真正要删除的
 
 -                     if "=" not in varEntry0.get():
 
 -                         varEntry0.set(varEntry0.get()[:-1])
 
 -                     elif "=" not in varEntry0.get():
 
 -                         if varLabel0.get()[-2:] == "//":
 
 -                             varLabel0.set(varLabel0.get()[:-2])
 
 -                         else:
 
 -                             varLabel0.set(varLabel0.get()[:-1])
 
  
-             elif txt in ("π", "√", "("):
 
 -                 try:
 
 -                     if is_old_entry_part():
 
 -                         fast_add(varEntry0, txt)
 
 -                         # 有 IndexError: list index out of range 的危险
 
 -                         if input_list[-2] in ("π", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"):
 
 -                             input_list.insert(-1, "*")
 
 -                 except Exception as e:
 
 -                     print(e)
 
  
-             elif txt in ("+", "-", "*", "/", "%", "//", "^", "!"):
 
 -                 if "=" in varEntry0.get():  # 上一个结果进行新运算
 
 -                     varEntry0.set("")
 
 -                     varLabel0.set("".join(input_list))
 
 -                     print("添加后", input_list)
 
 -                 elif any(map(lambda x: x in varLabel0.get(), ["+", "-", "*", "/", "%", "//", "^", "!"])):
 
 -                     varLabel0.set(varLabel0.get() + varEntry0.get() + txt)
 
 -                     varEntry0.set("")
 
 -                 else:
 
 -                     if "(" in varEntry0.get() and ")" not in varEntry0.get():  # 分行
 
 -                         fast_add(varEntry0, txt)  # 正常输入
 
 -                     else:
 
 -                         if "√" in varEntry0.get() and txt != "*":
 
 -                             varEntry0.set(get_result(input_list[:-1]) + txt)
 
 -                         elif txt == "-" and input_list[0] == "-" and input_list.count("-") == 1:  # 负号而不是减号
 
 -                             if is_old_entry_part():
 
 -                                 fast_add(varEntry0, txt)  # 正常输入
 
 -                         else:
 
 -                             varLabel0.set(varEntry0.get() + txt)
 
 -                             varEntry0.set("")
 
  
-             else:
 
 -                 if is_old_entry_part():
 
 -                     fast_add(varEntry0, txt)  # 正常输入数字的情况
 
  
 
- def split_list(lst, *delimiter):
 
 -     result = []
 
 -     current_part = []
 
 -     have_right_bracket = 0
 
 -     for item in lst:
 
 -         if item == "√":
 
 -             current_part.append("my_sqrt(")
 
 -             have_right_bracket += 1
 
 -         elif item == "π":
 
 -             current_part.append(str(pi))
 
 -         elif item in ("sin", "cos", "tan"):
 
 -             item = "my_" + item + "("
 
 -             have_right_bracket += 1
 
 -         elif item == "!":
 
 -             item = "my_factorial("
 
 -             have_right_bracket += 1
 
  
-         if item in delimiter:
 
 -             if item == "^":
 
 -                 item = "**"
 
 -             if current_part:  # 确保当前部分不为空
 
 -                 result.append(current_part)
 
 -                 current_part = []
 
 -                 if have_right_bracket and item != "(":
 
 -                     result.append(")")
 
 -                     have_right_bracket -= 1
 
 -             result.append(item)
 
 -         elif item not in ("√", ")", "π", "!"):
 
 -             current_part.append(item)  # 数字,三角函数
 
  
-     while have_right_bracket:
 
 -         current_part.append(")")
 
 -         have_right_bracket -= 1
 
 -     if current_part:  # 添加最后一部分(如果存在)
 
 -         result.append(current_part)
 
  
-     return result
 
  
 
- def get_result(lst, is_eq_click=False):
 
 -     splited_result = split_list(lst, "(", ")", "+", "-", "*", "/", "%", "//", "^")
 
 -     splited_result = ["".join(i) for i in splited_result]
 
 -     index = 0
 
 -     result = 0
 
 -     for each in splited_result:
 
 -         try:
 
 -             splited_result[index] = repr(Decimal(each))
 
 -         except Exception as e:
 
 -             print(e)
 
 -             print(each)
 
 -             print(splited_result)
 
 -         index += 1
 
  
-     try:
 
 -         print("WHYYYYYYYYYYYYY", splited_result)
 
 -         result = eval("".join(splited_result))
 
 -     except Exception as e:  # 可能由各种原因导致
 
 -         print("?????????", e)
 
 -         varEntry0.set("错误")
 
  
-     result = str(result)
 
  
-     try:
 
 -         if len(result.split(".")[1]) > digits_after_point:
 
 -             result = str(Decimal(result).quantize(Decimal(f"0.{'0' * digits_after_point}")))
 
 -     except Exception as e:
 
 -         print(e)
 
  
-     if len(result) >= 26:
 
 -         result = f"{Decimal(result):.{digits_after_point}e}"
 
  
-     if is_eq_click:
 
 -         history_input_list.extend([varLabel0.get()+varEntry0.get(), "=", result, "\n"])
 
  
-     return result
 
  
 
- def equal_click():
 
 -     global input_list
 
 -     result = str(get_result(input_list, True))
 
 -     if varEntry0.get() == "错误":
 
 -         input_list = input_list[:-1]
 
 -     else:
 
 -         input_list = [result]
 
 -         varLabel0.set(varLabel0.get() + varEntry0.get())
 
 -         varEntry0.set("=" + result)
 
  
 
- # 显示结果部分
 
  
- varLabel0 = ttk.StringVar()
 
 - varLabel0.set("计算过程区:")
 
 - label0 = ttk.Label(win, font=("宋体", 15), textvariable=varLabel0)
 
 - label0.grid(sticky=ttk.EW)  # 东西方向填充
 
 - varEntry0 = ttk.StringVar()
 
  
- entry0 = ttk.Entry(win, font=("微软雅黑", 15), textvariable=varEntry0)
 
 - entry0.grid(sticky=ttk.EW)  # 东西方向填充
 
 - entry0.bind("<Key>", lambda event: calcu(event, True))  # 绑定键盘事件
 
  
- # 按钮部分
 
 - # 创建frame框架
 
 - box = ttk.Frame(win)
 
 - box.grid(row=2, column=0)
 
  
- # 按钮文本的列表
 
  
- btn_text = ["(", ")", "x^y", "/", "π", "sin x",
 
 -             "7", "8", "9", "*", "√x", "cos x",
 
 -             "4", "5", "6", "-", "取余", "tan x",
 
 -             "1", "2", "3", "+", "整除", "x!",
 
 -             "0", ".", "+/-", "CE", "C"]
 
 - # 行和列
 
 - ri = 0
 
 - ci = 0
 
 - # 通过循环批量制作按钮
 
 - for v in btn_text:
 
 -     if ci != 0 and ci % 6 == 0:
 
 -         ri += 1  # 换行
 
 -         ci = 0  # 列变为0
 
 -     '''单击事件绑定
 
 -         1.command只能绑定一个,如果要传参可以用lambda表达式
 
 -         2.bind可以传当前控件事件到自定义函数'''
 
  
-     btn1 = ttk.Button(box, text=v, width=4, style="warning-outline")
 
  
-     btn1.bind("<Button-1>", calcu)  # 左键单击事件
 
 -     if ri == 4 and ci == 0:
 
 -         btn1.config(width=10)
 
 -         btn1.grid(row=ri, column=ci, columnspan=2)
 
 -         ci += 2
 
 -     else:
 
 -         btn1.grid(row=ri, column=ci)
 
 -         ci += 1
 
  
- # =按钮
 
 - pic_equal = Image.open("./py_pic/等于号.png")  # 载入图片对象
 
 - pic_equal = pic_equal.resize((225, 60))  # 一个元组
 
 - pic_equal = ImageTk.PhotoImage(pic_equal)  # 变成适合ttk的图片格式
 
 - btnEqual = ttk.Button(box, image=pic_equal, command=equal_click, style='danger-solid')
 
 - btnEqual.grid(row=ri + 1, column=0, columnspan=6, sticky=ttk.EW)
 
  
- win.mainloop()
 
 
  复制代码 
未来前景 
 
打算加上视觉识别,扩充功能 
 
大家发现 bug ,有建议可以提出! 
 
 
 
 
 
 不要吝啬评分 
 
 
 
 |   
 
评分
- 
查看全部评分
 
 
 
 
 
 |