浏览代码

函数系统 拆解对象

Huan 5 年之前
父节点
当前提交
71a56b3175
共有 4 个文件被更改,包括 1988 次插入1297 次删除
  1. 10 1270
      funcsystem/controller.py
  2. 6 5
      funcsystem/factory.py
  3. 22 22
      funcsystem/map.py
  4. 1950 0
      funcsystem/template.py

文件差异内容过多而无法显示
+ 10 - 1270
funcsystem/controller.py


+ 6 - 5
funcsystem/factory.py

@@ -201,11 +201,11 @@ def gradient_method_calculation():
     try:
     try:
         output_prompt("计算过程程序可能无响应")
         output_prompt("计算过程程序可能无响应")
         result_box.delete(0, tkinter.END)  # 清空
         result_box.delete(0, tkinter.END)  # 清空
-        E = []
+        parameters = []
         for i in gradient_parameters:
         for i in gradient_parameters:
-            E.append(i.get())
+            parameters.append(i.get())
         output_prompt("系统运算中")
         output_prompt("系统运算中")
-        answer = func.gradient_calculation(y_value_gradient.get(), *E)
+        answer = func.gradient_calculation(y_value_gradient.get(), *parameters)
         if answer[1] is not None:
         if answer[1] is not None:
             result_box.insert(tkinter.END, answer[0])
             result_box.insert(tkinter.END, answer[0])
             output_prompt("系统运算完成")
             output_prompt("系统运算完成")
@@ -221,7 +221,7 @@ def calculate():
         output_prompt("计算过程程序可能无响应")
         output_prompt("计算过程程序可能无响应")
         result_box.delete(0, tkinter.END)
         result_box.delete(0, tkinter.END)
         x = x_value.get().split(",")
         x = x_value.get().split(",")
-        answer = func.calculate(x)
+        answer = func.calculation(x)
         if answer != []:
         if answer != []:
             result_box.insert(tkinter.END, *answer)
             result_box.insert(tkinter.END, *answer)
             output_prompt("系统运算完毕")
             output_prompt("系统运算完毕")
@@ -718,7 +718,8 @@ def set_function():
         output_prompt("应用成功")
         output_prompt("应用成功")
         SCREEN.title(f"CoTan函数工厂  {func}")
         SCREEN.title(f"CoTan函数工厂  {func}")
     except BaseException:
     except BaseException:
-        output_prompt("应用失败")
+        output_prompt("应用失败2")
+        raise
 
 
 
 
 def output_prompt(news):
 def output_prompt(news):

+ 22 - 22
funcsystem/map.py

@@ -11,7 +11,7 @@ import pandas
 from matplotlib import pyplot as plt
 from matplotlib import pyplot as plt
 from matplotlib import rcParams
 from matplotlib import rcParams
 
 
-from funcsystem.controller import ExpFunc, SheetFunc
+from funcsystem.controller import SheetFunc, ExpFunc
 
 
 func_logger = []
 func_logger = []
 fig = None
 fig = None
@@ -169,9 +169,9 @@ def plot_func():
     plt.ylim(_y_limit)
     plt.ylim(_y_limit)
     # 函数绘图系统
     # 函数绘图系统
     output_prompt("图像绘制中...")
     output_prompt("图像绘制中...")
-    if not func_list:
+    if not func_logger:
         return False
         return False
-    for Fucn in func_list:
+    for Fucn in func_logger:
         get = Fucn.get_plot_data()
         get = Fucn.get_plot_data()
         plot_x = get[0]
         plot_x = get[0]
         plot_y = get[1]
         plot_y = get[1]
@@ -271,9 +271,9 @@ def add_from_csv():  # 添加函数
         name += "(In CSV)"
         name += "(In CSV)"
         _func = numpy.array(read).tolist()
         _func = numpy.array(read).tolist()
         func_str_list.append(name)
         func_str_list.append(name)
-        func_list.append(SheetFunc(_func, name, style))
+        func_logger.append(SheetFunc(_func, name, style))
         func_exp_box.delete(0, tkinter.END)
         func_exp_box.delete(0, tkinter.END)
-        func_exp_box.insert(tkinter.END, *func_list)
+        func_exp_box.insert(tkinter.END, *func_logger)
         output_prompt("读取完毕")
         output_prompt("读取完毕")
     except BaseException:
     except BaseException:
         output_prompt("读取失败")
         output_prompt("读取失败")
@@ -321,9 +321,9 @@ def add_func():  # 添加函数
         pass
         pass
     if get and get not in func_str_list:
     if get and get not in func_str_list:
         func_str_list.append(get)
         func_str_list.append(get)
-        func_list.append(ExpFunc(get, name, style, *definition))
+        func_logger.append(ExpFunc(get, name, style, *definition))
         func_exp_box.delete(0, tkinter.END)
         func_exp_box.delete(0, tkinter.END)
-        func_exp_box.insert(tkinter.END, *func_list)
+        func_exp_box.insert(tkinter.END, *func_logger)
         output_prompt("函数生成完毕")
         output_prompt("函数生成完毕")
     else:
     else:
         output_prompt("函数生成失败")
         output_prompt("函数生成失败")
@@ -333,7 +333,7 @@ def clean_func_box():  # 添加函数
     global func_logger, func_str_list, func_exp_box, func_name, line_style, point_style, func_style
     global func_logger, func_str_list, func_exp_box, func_name, line_style, point_style, func_style
     if tkinter.messagebox.askokcancel("提示", "是否清空所有函数?)"):
     if tkinter.messagebox.askokcancel("提示", "是否清空所有函数?)"):
         func_str_list = []
         func_str_list = []
-        func_list = []
+        func_logger = []
         func_exp_box.delete(0, tkinter.END)
         func_exp_box.delete(0, tkinter.END)
         output_prompt("函数清空完毕")
         output_prompt("函数清空完毕")
 
 
@@ -341,7 +341,7 @@ def clean_func_box():  # 添加函数
 def func_to_sheet():  # 显示xy
 def func_to_sheet():  # 显示xy
     global func_logger, func_exp_box, sheet_box
     global func_logger, func_exp_box, sheet_box
     try:
     try:
-        func = func_list[func_exp_box.curselection()[0]]
+        func = func_logger[func_exp_box.curselection()[0]]
         sheet_box.delete(0, tkinter.END)
         sheet_box.delete(0, tkinter.END)
         sheet_box.insert(tkinter.END, *func.return_list())
         sheet_box.insert(tkinter.END, *func.return_list())
         output_prompt("表格创建成功")
         output_prompt("表格创建成功")
@@ -354,10 +354,10 @@ def clean_func_memory():
     global x_value, func_exp_box, func_logger
     global x_value, func_exp_box, func_logger
     try:
     try:
         if tkinter.messagebox.askokcancel(
         if tkinter.messagebox.askokcancel(
-            "提示", f"确定删除{func_list[func_exp_box.curselection()[0]]}的记忆吗?"
+            "提示", f"确定删除{func_logger[func_exp_box.curselection()[0]]}的记忆吗?"
         ):
         ):
             result_box.delete(0, tkinter.END)
             result_box.delete(0, tkinter.END)
-            fucn = func_list[func_exp_box.curselection()[0]]
+            fucn = func_logger[func_exp_box.curselection()[0]]
             fucn.clean_memory()
             fucn.clean_memory()
             output_prompt("删除完毕")
             output_prompt("删除完毕")
         else:
         else:
@@ -369,7 +369,7 @@ def clean_func_memory():
 def hide_memory():  # 显示xy
 def hide_memory():  # 显示xy
     global func_logger, result_box
     global func_logger, result_box
     try:
     try:
-        func = func_list[func_exp_box.curselection()[0]]
+        func = func_logger[func_exp_box.curselection()[0]]
         result_box.delete(0, tkinter.END)
         result_box.delete(0, tkinter.END)
         func.hide_or_show()
         func.hide_or_show()
         output_prompt("已清空卡槽")
         output_prompt("已清空卡槽")
@@ -380,7 +380,7 @@ def hide_memory():  # 显示xy
 def show_memory():  # 显示xy
 def show_memory():  # 显示xy
     global func_logger, result_box
     global func_logger, result_box
     try:
     try:
-        fucn = func_list[func_exp_box.curselection()[0]]
+        fucn = func_logger[func_exp_box.curselection()[0]]
         result_box.delete(0, tkinter.END)
         result_box.delete(0, tkinter.END)
         m_x, m_y = fucn.get_memory()
         m_x, m_y = fucn.get_memory()
         answer = []
         answer = []
@@ -396,7 +396,7 @@ def property_prediction():
     global func_logger, func_exp_box, property_box
     global func_logger, func_exp_box, property_box
     try:
     try:
         output_prompt("预测过程程序可能无响应")
         output_prompt("预测过程程序可能无响应")
-        fucn = func_list[func_exp_box.curselection()[0]]
+        fucn = func_logger[func_exp_box.curselection()[0]]
         property_box.delete(0, tkinter.END)
         property_box.delete(0, tkinter.END)
         answer = fucn.property_prediction(output_prompt)
         answer = fucn.property_prediction(output_prompt)
         property_box.insert(tkinter.END, *answer)
         property_box.insert(tkinter.END, *answer)
@@ -409,10 +409,10 @@ def calculate():
     global func_logger, result_box, x_value, func_exp_box
     global func_logger, result_box, x_value, func_exp_box
     try:
     try:
         output_prompt("计算过程程序可能无响应")
         output_prompt("计算过程程序可能无响应")
-        fucn = func_list[func_exp_box.curselection()[0]]
+        fucn = func_logger[func_exp_box.curselection()[0]]
         result_box.delete(0, tkinter.END)
         result_box.delete(0, tkinter.END)
         x = x_value.get().split(",")
         x = x_value.get().split(",")
-        answer = fucn.calculate(x)
+        answer = fucn.calculation(x)
         result_box.insert(tkinter.END, *answer)
         result_box.insert(tkinter.END, *answer)
         output_prompt("系统计算完毕")
         output_prompt("系统计算完毕")
     except IndexError:
     except IndexError:
@@ -436,7 +436,7 @@ def del_func():  # 删除函数
     del_fucn = func_exp_box.curselection()
     del_fucn = func_exp_box.curselection()
     for i in del_fucn:  # 只存在一项
     for i in del_fucn:  # 只存在一项
         func_exp_box.delete(i)
         func_exp_box.delete(i)
-        del func_list[i]
+        del func_logger[i]
         del func_str_list[i]
         del func_str_list[i]
         output_prompt("函数删除完毕")
         output_prompt("函数删除完毕")
 
 
@@ -445,7 +445,7 @@ def dichotomy():
     global func_logger, result_box, y_value, dicon_parameters
     global func_logger, result_box, y_value, dicon_parameters
     try:
     try:
         output_prompt("计算过程程序可能无响应")
         output_prompt("计算过程程序可能无响应")
-        fucn = func_list[func_exp_box.curselection()[0]]  # 获取目标函数
+        fucn = func_logger[func_exp_box.curselection()[0]]  # 获取目标函数
         result_box.delete(0, tkinter.END)  # 清空
         result_box.delete(0, tkinter.END)  # 清空
         y = y_value.get().split(",")  # 拆解输入
         y = y_value.get().split(",")  # 拆解输入
         parameters = dicon_parameters.get().split("#")  # 拆解输入
         parameters = dicon_parameters.get().split("#")  # 拆解输入
@@ -467,7 +467,7 @@ def gradient_method_calculation():
     global func_logger, result_box, y_value_gradient
     global func_logger, result_box, y_value_gradient
     try:
     try:
         output_prompt("计算过程程序可能无响应")
         output_prompt("计算过程程序可能无响应")
-        fucn = func_list[func_exp_box.curselection()[0]]  # 获取目标函数
+        fucn = func_logger[func_exp_box.curselection()[0]]  # 获取目标函数
         result_box.delete(0, tkinter.END)  # 清空
         result_box.delete(0, tkinter.END)  # 清空
         parameters = y_value_gradient.get().split("#")  # 拆解输入
         parameters = y_value_gradient.get().split("#")  # 拆解输入
         output_prompt("系统运算中")
         output_prompt("系统运算中")
@@ -493,12 +493,12 @@ def output_prompt(news):
 def func_differentiation():
 def func_differentiation():
     global func_logger, func_exp_box, property_box, func_str_list, func_name, line_style, point_style, func_style
     global func_logger, func_exp_box, property_box, func_str_list, func_name, line_style, point_style, func_style
     try:
     try:
-        fucn = func_list[func_exp_box.curselection()[0]]
+        fucn = func_logger[func_exp_box.curselection()[0]]
         diff = fucn.derivatives
         diff = fucn.derivatives
         if diff is not None and str(diff):
         if diff is not None and str(diff):
             get = str(diff)
             get = str(diff)
             func_str_list.append(get)
             func_str_list.append(get)
-            func_list.append(
+            func_logger.append(
                 ExpFunc(
                 ExpFunc(
                     get,
                     get,
                     "(导)" + fucn.Func_Name + " Of ",
                     "(导)" + fucn.Func_Name + " Of ",
@@ -510,7 +510,7 @@ def func_differentiation():
                 )
                 )
             )
             )
             func_exp_box.delete(0, tkinter.END)
             func_exp_box.delete(0, tkinter.END)
-            func_exp_box.insert(tkinter.END, *func_list)
+            func_exp_box.insert(tkinter.END, *func_logger)
             output_prompt("函数生成完毕")
             output_prompt("函数生成完毕")
         else:
         else:
             raise Exception
             raise Exception

+ 1950 - 0
funcsystem/template.py

@@ -0,0 +1,1950 @@
+from __future__ import division  # 让/恢复为除法
+import tkinter
+import tkinter.messagebox
+from abc import ABCMeta, abstractmethod
+import tkinter.messagebox
+
+import pandas
+import sympy
+
+
+def to_bool(str_object, hope=False):
+    false_list = ["0", "n", "no", "NO", "NOT", "No", "Not", "不"]
+    true_list = ["y", "yes", "Yes", "YES", "不"]
+    if hope:
+        true_list.append("")
+    else:
+        false_list.append("")
+    try:
+        str_object = str(str_object)
+        if str_object in false_list:
+            return False
+        elif str_object in true_list:
+            return True
+        else:
+            raise Exception
+    except BaseException:
+        return bool(str_object)
+
+
+def find_x_by_y(x_list, y_list, y):  # 输入x和y照除In_Y的所有对应x值
+    m = []
+    while True:
+        try:
+            num = y_list.index(y)
+            m.append(x_list[num])
+            del x_list[num]
+            del y_list[num]
+        except ValueError:
+            break
+    return m
+
+
+class FuncBase:
+    @abstractmethod
+    def best_value_core(self):
+        pass
+
+    @abstractmethod
+    def data_packet(self, number_type):
+        pass
+
+    @abstractmethod
+    def gradient_calculation(self, y_value, start, end, max_iter, accuracy):
+        pass
+
+    @abstractmethod
+    def dichotomy(self, y_value, **kwargs):
+        pass
+
+    @abstractmethod
+    def parity(self, precision):
+        pass
+
+    @abstractmethod
+    def monotonic(self):
+        pass
+
+    @abstractmethod
+    def property_prediction(self, output_prompt, return_all, accuracy):
+        pass
+
+    @abstractmethod
+    def hide_or_show(self):
+        pass
+
+    @abstractmethod
+    def save_csv(self):
+        pass
+
+    @abstractmethod
+    def return_list(self):
+        pass
+
+    @abstractmethod
+    def best_value(self):
+        pass
+
+    @abstractmethod
+    def get_memory(self):
+        pass
+
+    @abstractmethod
+    def clean_memory(self):
+        pass
+
+    @abstractmethod
+    def get_plot_data(self):
+        pass
+
+    @abstractmethod
+    def calculation(self, x_in):
+        pass
+
+    @abstractmethod
+    def periodic(self, output_prompt, accuracy):
+        pass
+
+    @abstractmethod
+    def symmetry_axis(self, output_prompt, accuracy):
+        pass
+
+    @abstractmethod
+    def symmetry_center(self, output_prompt, accuracy):
+        pass
+
+
+class SheetFuncBase(FuncBase, metaclass=ABCMeta):
+    @abstractmethod
+    def dichotomy(self, y_in, *args, **kwargs):
+        pass
+
+    @abstractmethod
+    def data_packet(self, *args, **kwargs):
+        pass
+
+    @abstractmethod
+    def property_prediction(self, output_prompt, **kwargs):
+        pass
+
+    @abstractmethod
+    def periodic(self, output_prompt, **kwargs):
+        pass
+
+    @abstractmethod
+    def symmetry_axis(self, output_prompt, **kwargs):
+        pass
+
+    @abstractmethod
+    def symmetry_center(self, output_prompt, **kwargs):
+        pass
+
+
+class ExpFuncBase(FuncBase, metaclass=ABCMeta):
+    @abstractmethod
+    def return_son(self):
+        pass
+
+    @abstractmethod
+    def check_monotonic(self, parameters, output_prompt, accuracy):
+        pass
+
+    @abstractmethod
+    def check_periodic(self, parameters, output_prompt, accuracy):
+        pass
+
+    @abstractmethod
+    def check_symmetry_axis(self, parameters, output_prompt, accuracy):
+        pass
+
+    @abstractmethod
+    def check_symmetry_center(self, parameters_input, output_prompt, accuracy):
+        pass
+
+    @abstractmethod
+    def sympy_calculation(self, y_value):
+        pass
+
+    @abstractmethod
+    def derivative(self, x_value, delta_x, must):
+        pass
+
+
+class SheetFuncInit:
+    def __init__(self, func, name, style):
+        # 筛查可以数字化的结果
+        float_x_list = []
+        float_y_list = []
+        for i in range(len(func[0])):  # 检查
+            try:
+                float_x = float(func[0][i])
+                float_y = float(func[1][i])
+                float_x_list.append(float_x)
+                float_y_list.append(float_y)
+            except BaseException:
+                pass
+        # 筛查重复
+        x = []
+        y = []
+        for x_index in range(len(float_x_list)):
+            now_x = float_x_list[x_index]
+            if now_x in x:
+                continue
+            y.append(float_y_list[x_index])
+            x.append(now_x)
+
+        # 函数基本信息
+        self.func_name = name  # 这个是函数名字
+        self.style = style  # 绘制样式
+
+        # 函数基本数据,相当于Lambda的Cul
+        self.x = x
+        self.y = y
+        self.y_real = y
+        self.classification_x = []
+        self.classification_y = []
+        self.xy_sheet = []
+        for i in range(len(self.x)):
+            self.xy_sheet.append(f"x:{self.x[i]},y:{self.y[i]}")
+        self.dataframe = pandas.DataFrame((self.x, self.y), index=("x", "y"))
+
+        self.span = (max(x) - min(x)) / len(x)
+
+        # 函数记忆数据
+        self.memore_x = []
+        self.memore_y = []
+        self.memory_answer = []
+
+        self.have_prediction = False
+        self.best_r = None
+        self.have_data_packet = False
+
+        self.max_y = None
+        self.max_x = []
+        self.min_y = None
+        self.min_x = []
+
+    def __call__(self, x):
+        return self.y[self.x.index(x)]
+
+    def __str__(self):
+        return f"{self.func_name}"
+
+
+class SheetDataPacket(SheetFuncInit, metaclass=ABCMeta):
+    @abstractmethod
+    def best_value_core(self):
+        pass
+
+    def data_packet(self, *args, **kwargs):
+        if self.have_data_packet:
+            return self.x, self.y, self.func_name, self.style
+        self.classification_x = [[]]
+        self.classification_y = [[]]
+        last_y = None
+        last_monotonic = None  # 单调性 0-增,1-减
+        now_monotonic = 1
+        classification_reason = [100]  # 第一断组原因为100
+        try:
+            for now_x in self.x:
+                group_score = 0
+                balance = 1
+                try:
+                    y = self(now_x)
+                    if last_y is not None and last_y > y:
+                        now_monotonic = 1
+                    elif last_y is not None and last_y < y:
+                        now_monotonic = 0
+                    elif last_y is not None and last_y == y:
+                        try:
+                            if last_y == y:  # 真实平衡
+                                balance = 2
+                            elif abs(y - last_y) >= 10 * self.span:
+                                balance = 3
+                                group_score += 5
+                        except BaseException:
+                            balance = 4
+                            group_score += 9
+                        now_monotonic = 2
+                    if last_y is not None and last_monotonic != now_monotonic:
+                        if (last_y * y) < 0:
+                            group_score += 5
+                        elif abs(last_y - y) >= (10 * self.span):
+                            group_score += 5
+                        if group_score >= 5 and (now_monotonic != 2 or balance != 2):
+                            classification_reason.append(group_score)
+                            self.classification_x.append([])
+                            self.classification_y.append([])
+                    last_monotonic = now_monotonic
+                    self.classification_x[-1].append(now_x)
+                    self.classification_y[-1].append(y)
+                    last_y = y
+                except BaseException:
+                    pass
+        except (TypeError, IndexError, ValueError):
+            pass
+        classification_reason.append(99)
+        new_classification_x = []
+        new_classification_y = []
+        must_forward = False
+        for i in range(len(self.classification_x)):  # 去除只有单个的组群
+            if len(self.classification_x[i]) == 1 and not must_forward:  # 检测到有单个群组
+                front_reason = classification_reason[i]  # 前原因
+                back_reason = classification_reason[i + 1]  # 后原因
+                if front_reason < back_reason:  # 前原因小于后原因,连接到前面
+                    try:
+                        new_classification_x[-1] += self.classification_x[i]
+                        new_classification_y[-1] += self.classification_y[i]
+                    except BaseException:  # 按道理不应该出现这个情况
+                        new_classification_x.append(self.classification_x[i])
+                        new_classification_y.append(self.classification_y[i])
+                else:
+                    new_classification_x.append(self.classification_x[i])
+                    new_classification_y.append(self.classification_y[i])
+                    must_forward = True
+            else:
+                if not must_forward:
+                    new_classification_x.append(self.classification_x[i])
+                    new_classification_y.append(self.classification_y[i])
+                else:
+                    new_classification_x[-1] += self.classification_x[i]
+                    new_classification_y[-1] += self.classification_y[i]
+                    must_forward = False
+        self.classification_x = new_classification_x
+        self.classification_y = new_classification_y
+        self.have_data_packet = True
+        self.dataframe = pandas.DataFrame((self.x, self.y), index=("x", "y"))
+        self.best_value_core()
+        return self.x, self.y, self.func_name, self.style
+
+
+class SheetBestValue(SheetDataPacket):
+    def best_value_core(self):  # 计算最值和极值点
+        if not self.have_data_packet:
+            self.data_packet()  # 检查Cul的计算
+        y = self.y + self.memore_y
+        x = self.x + self.memore_x
+        max_y = max(y)
+        min_y = min(y)
+        max_x = find_x_by_y(x.copy(), y.copy(), max_y)
+        self.max_y = max_y
+        self.max_x = max_x
+        min_x = find_x_by_y(x.copy(), y.copy(), min_y)
+        self.min_y = min_y
+        self.min_x = min_x
+        return self.max_x, self.max_y, self.min_x, self.min_y
+
+    def best_value(self):
+        if not self.have_data_packet:
+            self.data_packet()  # 检查Cul的计算
+        return self.max_x, self.max_y, self.min_x, self.min_y
+
+
+class SheetComputing(SheetBestValue):
+    def gradient_calculation(self, y_in, *args, **kwargs):  # 保持和下一个对象相同参数
+        result = self.dichotomy(y_in)
+        return result[0], result[0][0]
+
+    def dichotomy(self, y_in, *args, **kwargs):  # 保持和下一个对象相同参数
+        y_list = sorted(self.y.copy())
+        last_y = None  # o_y是比较小的,i是比较大的
+        result = None
+        for i in y_list:
+            try:
+                if (last_y < y_in and i > y_in) and (
+                    abs(((i + last_y) / 2) - y_in) < 0.1
+                ):
+                    result = [last_y, i]
+                    break
+            except BaseException:
+                pass
+            last_y = i
+        if result is None:
+            for i in y_list:
+                try:
+                    if abs(((i + last_y) / 2) - y_in) < 0.1:
+                        result = [last_y, i]
+                        break
+                except BaseException:
+                    pass
+                last_y = i
+        if result is None:
+            return [], []
+        last_x = find_x_by_y(self.x.copy(), self.y.copy(), result[0])  # last_y的x
+        now_x = find_x_by_y(self.x.copy(), self.y.copy(), result[1])
+        x_len = min([len(now_x), len(last_x)])
+        answer = []
+        result = []
+        for i in range(x_len):
+            r = (now_x[i] + last_x[i]) / 2
+            self.memore_x.append(r)
+            self.memore_y.append(y_in)
+            result.append(r)
+            answer.append(f"y={y_in} -> x={r}")
+        self.memory_answer += answer
+        return answer, result
+
+    def calculation(self, x_list):
+        answer = []
+        for i in x_list:
+            try:
+                i = float(i)
+                y = self(i)
+                answer.append(f"x={i} -> y={y}")
+                if i not in self.memore_x:
+                    self.memore_x.append(i)
+                    self.memore_y.append(y)
+            except BaseException:  # 捕捉运算错误
+                continue
+        self.memory_answer += answer
+        self.best_value_core()
+        return answer
+
+
+class SheetProperty(SheetComputing):
+    def parity(self, *args, **kwargs):  # 奇偶性
+        if not self.have_data_packet:
+            self.data_packet()  # 检查Cul的计算
+        x = self.x.copy()
+        left_x = sorted(x)[0]
+        right_x = sorted(x)[1]
+        left_x = -min([abs(left_x), abs(right_x)])
+        right_x = -left_x
+        flat = None  # 0-偶函数,1-奇函数
+        for i in range(len(x)):
+            now_x = x[i]  # 正项x
+            if now_x < left_x or now_x > right_x:
+                continue  # x不在区间内
+            try:
+                now_y = self(now_x)
+                symmetry_y = self(-now_x)
+
+                if symmetry_y == now_y == 0:
+                    continue
+                elif symmetry_y == now_y:
+                    if flat is None:
+                        flat = 0
+                    elif flat == 1:
+                        raise Exception
+                elif symmetry_y == -now_y:
+                    if flat is None:
+                        flat = 1
+                    elif flat == 0:
+                        raise Exception
+                else:
+                    raise Exception
+            except BaseException:
+                flat = None
+                break
+        return flat, [left_x, right_x]
+
+    def monotonic(self):  # 单调性
+        if not self.have_data_packet:
+            self.data_packet()  # 运行Cul计算
+        classification_x = self.classification_x.copy()
+        increase_interval = []  # 增区间
+        minus_interval = []  # 减区间
+        interval = []  # 不增不减
+        for i in range(len(classification_x)):
+            x_list = classification_x[i]
+            y_list = classification_x[i]
+            last_x = None
+            last_y = None
+            start_x = None
+            flat = None  # 当前研究反围:0-增区间,1-减区间,2-不增不减
+            for a in range(len(x_list)):
+                now_x = x_list[a]  # 正项x
+                now_y = y_list[a]  # 正项y
+                if start_x is None:
+                    start_x = now_x
+                else:
+                    if last_y > now_y:  # 减区间
+                        if flat is None or flat == 1:  # 减区间
+                            pass
+                        elif flat == 0:  # 增区间
+                            increase_interval.append((start_x, last_x))
+                            start_x = last_x
+                        elif flat == 2:
+                            interval.append((start_x, last_x))
+                            start_x = last_x
+                        flat = 1
+                    elif last_y < now_y:  # 增区间
+                        if flat is None or flat == 0:  # 增区间
+                            pass
+                        elif flat == 1:  # 减区间
+                            minus_interval.append((start_x, last_x))
+                            start_x = last_x
+                        elif flat == 2:
+                            interval.append((start_x, last_x))
+                            start_x = last_x
+                        flat = 0
+                    else:  # 水平区间
+                        if flat is None or flat == 2:
+                            pass
+                        elif flat == 1:  # 减区间
+                            minus_interval.append((start_x, last_x))
+                            start_x = last_x
+                        elif flat == 0:  # 增区间
+                            increase_interval.append((start_x, last_x))
+                            start_x = last_x
+                        flat = 2
+                last_x = now_x
+                last_y = now_y
+            if flat == 2:
+                interval.append((start_x, last_x))
+            elif flat == 1:  # 减区间
+                minus_interval.append((start_x, last_x))
+            elif flat == 0:  # 增区间
+                increase_interval.append((start_x, last_x))
+        return increase_interval, minus_interval, interval
+
+    def property_prediction(self, output_prompt=lambda x: x, **kwargs):
+        answer = []
+        parity = self.parity()
+        monotonic = self.monotonic()
+        cycles = self.periodic(output_prompt)[0]
+        symmetry_axis = self.symmetry_axis(output_prompt)[0]
+        center_of_symmetry = self.symmetry_center(output_prompt)[0]
+        if parity[0] == 1:
+            answer.append(f"奇函数 区间:[{parity[1][0]},{parity[1][0]}]")
+        elif parity[0] == 0:
+            answer.append(f"偶函数 区间:[{parity[1][0]},{parity[1][0]}]")
+        for i in monotonic[0]:
+            answer.append(f"增区间:[{i[0]},{i[1]}]")
+        for i in monotonic[1]:
+            answer.append(f"减区间:[{i[0]},{i[1]}]")
+        for i in monotonic[2]:
+            answer.append(f"水平区间:[{i[0]},{i[1]}]")
+        if cycles is not None:
+            answer.append(f"最小正周期:{cycles}")
+        if symmetry_axis is not None:
+            answer.append(f"对称轴:x={symmetry_axis}")
+        if center_of_symmetry is not None:
+            answer.append(f"对称中心:{center_of_symmetry}")
+        return answer
+
+
+    def periodic(self, output_prompt=lambda x: x, **kwargs):  # 计算周期
+        if not tkinter.messagebox.askokcancel("提示", f"计算周期需要一定时间,是否执行?(计算过程程序可能无响应)"):
+            return None, []  # 无结果
+        if not self.have_data_packet:
+            self.data_packet()
+        possible_cycle_list = []  # 可能的周期
+        iteration_length = len(self.x)
+        iteration_interval = int(iteration_length / 20)
+        output_prompt("正在预测可能的周期")
+        for i in range(0, iteration_length, iteration_interval):
+            start = self.x[i]
+            try:
+                y = self(start)
+                x_list = self.dichotomy(y)[1]
+                possible_cycle = []
+                for x in x_list:
+                    a = abs(x - start)
+                    if a == 0:
+                        continue
+                    possible_cycle.append(a)
+                possible_cycle_list.extend(
+                    list(set(possible_cycle))
+                )  # 这里是extend不是append,相当于 +=
+            except BaseException:
+                pass
+
+        possible_cycle = []  # a的可能列表
+        max_count = 0
+        output_prompt("正在筛选结果")
+        for i in list(set(possible_cycle_list)):
+            count = possible_cycle_list.count(i)
+            if count > max_count:
+                possible_cycle = [i]
+                max_count = count
+            elif count == max_count:
+                possible_cycle.append(i)
+        try:
+            possible_cycle.sort()
+            output_prompt("计算完毕")
+            return possible_cycle[0], possible_cycle
+        except BaseException:
+            output_prompt("无周期")
+            return None, []  # 无结果
+
+    def symmetry_axis(self, output_prompt=lambda x: x, **kwargs):  # 计算对称轴
+        if not tkinter.messagebox.askokcancel("提示", f"计算对称轴需要一定时间,是否执行?(计算过程程序可能无响应)"):
+            return None, []  # 无结果
+        if not self.have_data_packet:
+            self.data_packet()
+        possible_symmetry_axis_list = []  # 可能的对称轴
+        iteration_length = len(self.x)
+        iteration_interval = int(iteration_length / 20)
+        output_prompt("正在预测可能的对称轴")
+        for i in range(0, iteration_length, iteration_interval):
+            start = self.x[i]
+            try:
+                y = self(start)
+                x_list = self.dichotomy(y)[1]
+                possible_symmetry_axis = []
+                for x in x_list:
+                    a = (x + start) / 2
+                    if possible_symmetry_axis:
+                        possible_symmetry_axis.append(a)
+                possible_symmetry_axis_list.extend(list(set(possible_symmetry_axis)))
+            except BaseException:
+                pass
+
+        possible_symmetry_axis = []  # a的可能列表
+        max_count = 0
+        output_prompt("正在筛选结果")
+        for i in list(set(possible_symmetry_axis_list)):
+            count = possible_symmetry_axis_list.count(i)
+            if count > max_count:
+                possible_symmetry_axis = [i]
+                max_count = count
+            elif count == max_count:
+                possible_symmetry_axis.append(i)
+        try:
+            possible_symmetry_axis.sort()  #
+            output_prompt("计算完毕")
+            return possible_symmetry_axis[0], possible_symmetry_axis
+        except BaseException:
+            output_prompt("无对称轴")
+            return None, []  # 无结果
+
+    def symmetry_center(self, output_prompt=lambda x: x, **kwargs):  # 计算对称中心
+        if not tkinter.messagebox.askokcancel("提示", f"计算对称中心需要一定时间,是否执行?(计算过程程序可能无响应)"):
+            return None, []  # 无结果
+        if not self.have_data_packet:
+            self.data_packet()
+        coordinate_points = []
+        iteration_length = len(self.x)
+        iteration_interval = int(iteration_length / 20)
+        output_prompt("正在计算坐标点")
+        for i in range(0, iteration_length, iteration_interval):
+            start = self.x[i]
+            try:
+                y = self(start)
+                x = start
+                coordinate_points.append((x, y))
+            except BaseException:
+                pass
+
+        possible_center_list = []
+        output_prompt("正在预测对称中心")
+        for i in coordinate_points:
+            for o in coordinate_points:
+                x = i[0] + o[0] / 2
+                y = i[1] + o[1] / 2
+                if i == o:
+                    continue
+                possible_center_list.append((x, y))
+
+        possible_center = []  # a的可能列表
+        max_count = 0
+        output_prompt("正在筛选结果")
+        for i in list(set(possible_center_list)):
+            count = possible_center_list.count(i)
+            if count > max_count:
+                possible_center = [i]
+                max_count = count
+            elif count == max_count:
+                possible_center.append(i)
+        try:
+            if max_count < 5:
+                raise Exception
+            output_prompt("计算完毕")
+            possible_center.sort()
+            return possible_center[int(len(possible_center) / 2)], possible_center
+        except BaseException:
+            output_prompt("无对称中心")
+            return None, []  # 无结果
+
+
+class SheetMemory(SheetFuncInit):
+    def hide_or_show(self):
+        if self.have_prediction:
+            if tkinter.messagebox.askokcancel("提示", f"是否显示{self}的记忆数据?"):
+                self.have_prediction = False
+        else:
+            if tkinter.messagebox.askokcancel("提示", f"是否隐藏{self}的记忆数据?"):
+                self.have_prediction = True
+
+    def clean_memory(self):
+        self.memore_x = []
+        self.memore_y = []
+        self.memory_answer = []
+
+    def get_memory(self):
+        if self.have_prediction:
+            return [], []
+        return self.memore_x, self.memore_y
+
+
+class ExpFuncInit:
+    def __init__(
+        self,
+        func,
+        name,
+        style,
+        start=-10,
+        end=10,
+        span=0.1,
+        accuracy=2,
+        a_default=1,
+        a_start=-10,
+        a_end=10,
+        a_span=1,
+        have_son=False,
+    ):
+        self.symbol_x = sympy.Symbol("x")
+        named_domain = {
+            "a": a_default,
+            "x": self.symbol_x,
+            "Pi": sympy.pi,
+            "e": sympy.E,
+            "log": sympy.log,
+            "sin": sympy.sin,
+            "cos": sympy.cos,
+            "tan": sympy.tan,
+            "cot": lambda x: 1 / sympy.tan(x),
+            "csc": lambda x: 1 / sympy.sin(x),
+            "sec": lambda x: 1 / sympy.cos(x),
+            "sinh": sympy.sinh,
+            "cosh": sympy.cosh,
+            "tanh": sympy.tanh,
+            "asin": sympy.asin,
+            "acos": sympy.acos,
+            "atan": sympy.atan,
+            "abs": abs,
+        }  # 这个是函数命名域
+        self.func = eval(func.replace(" ", ""), named_domain)  # 函数解析式
+        self.func_str = func.replace(" ", "")
+        # 函数基本信息
+        self.style = style  # 绘制样式
+        # 数据辨析
+        try:
+            start = float(start)
+            end = float(end)
+            if start > end:  # 使用float确保输入是数字,否则诱发ValueError
+                start, end = end, start
+            span = abs(float(span))
+            start = (start // span) * span  # 确保start可以恰好被kd整除
+            end = (end // span + 1) * span
+            accuracy = abs(int(accuracy))
+            if accuracy >= 3:
+                accuracy = 3
+        except ValueError:
+            start, end, span, accuracy = -10, 10, 0.1, 2  # 保底设置
+        # 基本数据存储
+        self.accuracy = accuracy
+        self.start = start
+        self.end = end
+        self.span = span
+
+        # x和y数据存储
+        self.x = []
+        self.y = []
+        self.y_real = []
+        self.classification_x = [[]]
+        self.classification_y = [[]]
+
+        # 记忆数据存储
+        self.memore_x = []
+        self.memore_y = []
+        self.memory_answer = []
+
+        # 最值和极值点
+        self.max_y = None
+        self.max_x = []
+        self.min_y = None
+        self.min_x = []
+
+        self.have_prediction = False
+        self.best_r = None  # 是否计算最值
+        self.have_data_packet = False  # 是否已经计算过xy
+
+        # 函数求导
+        try:
+            self.derivatives = sympy.diff(self.func, self.symbol_x)
+        except BaseException:
+            self.derivatives = None
+
+        # 儿子函数
+        try:
+            a_start = float(a_start)
+            a_end = float(a_end)
+            if a_start > a_end:  # 使用float确保输入是数字,否则诱发ValueError
+                a_start, a_end = a_end, a_start
+            a_span = abs(float(a_span))
+        except ValueError:
+            a_start, a_end, a_span = -10, 10, 1  # 保底设置
+        if have_son:
+            self.son_list = []
+            while a_start <= a_end:
+                try:
+                    self.son_list.append(
+                        ExpFuncSon(func, style, start, end, span, accuracy, a_start)
+                    )
+                except BaseException:
+                    pass  # 不应该出现
+                a_start += a_span
+            # 这个是函数名字
+            self.func_name = (
+                f"{name}:y={func} a={a_default}({a_start},{a_end},{a_span})"
+            )
+        else:
+            self.son_list = []
+            self.func_name = f"{name}:y={func} a={a_default})"  # 这个是函数名字
+
+    def __call__(self, x):
+        return self.func.subs({self.symbol_x: x})
+
+    def __str__(self):
+        return f"{self.func_name} {self.start, self.end, self.span}"
+
+
+class ExpDataPacket(ExpFuncInit, metaclass=ABCMeta):
+    @abstractmethod
+    def best_value_core(self):
+        pass
+
+    def data_packet(self, number_type=float):
+        if self.have_data_packet:
+            return self.x, self.y, self.func_name, self.style
+        # 混合存储
+        self.y = []
+        self.y_real = []
+        self.x = []
+        self.xy_sheet = []
+        self.classification_x = [[]]
+        self.classification_y = [[]]
+        classification_reason = [100]
+        last_y = None
+        last_monotonic = None  # 单调性 0-增,1-减
+        now_monotonic = 1
+        try:
+            now_x = int(self.start)
+            while now_x <= int(self.end):  # 因为range不接受小数
+                group_score = 0
+                balance = 1
+                try:
+                    accuracy_x = round(now_x, self.accuracy)
+                    now_y = number_type(self(accuracy_x))  # 数字处理方案
+                    accuracy_y = round(now_y, self.accuracy)
+                    if last_y is not None and last_y > now_y:
+                        now_monotonic = 1
+                    elif last_y is not None and last_y < now_y:
+                        now_monotonic = 0
+                    elif last_y is not None and last_y == now_y:
+                        try:
+                            middle_y = self(round(accuracy_x - 0.5 * self.span))
+                            if middle_y == last_y == now_y:  # 真实平衡
+                                balance = 2
+                            elif (
+                                abs(middle_y - last_y) >= 10 * self.span
+                                or abs(middle_y - now_y) >= 10 * self.span
+                            ):
+                                balance = 3
+                                group_score += 5
+                        except BaseException:
+                            balance = 4
+                            group_score += 9
+                        now_monotonic = 2
+                    if last_y is not None and last_monotonic != now_monotonic:
+                        if (last_y * now_y) < 0:
+                            group_score += 5
+                        elif abs(last_y - now_y) >= (10 * self.span):
+                            group_score += 5
+                        if group_score >= 5 and (now_monotonic != 2 or balance != 2):
+                            classification_reason.append(group_score)
+                            self.classification_x.append([])
+                            self.classification_y.append([])
+                    last_monotonic = now_monotonic
+                    self.x.append(accuracy_x)  # 四舍五入减少计算量
+                    self.y.append(now_y)  # 不四舍五入
+                    self.y_real.append(accuracy_y)  # 四舍五入(用于求解最值)
+                    self.xy_sheet.append(f"x:{accuracy_x},y:{accuracy_y}")
+                    self.classification_x[-1].append(accuracy_x)
+                    self.classification_y[-1].append(now_y)
+                    last_y = now_y
+                except BaseException:
+                    classification_reason.append(0)
+                    self.classification_x.append([])
+                    self.classification_y.append([])
+                now_x += self.span
+        except (TypeError, IndexError, ValueError):
+            pass
+        new_classification_x = []
+        new_classification_y = []
+        classification_reason.append(99)
+        must_forward = False
+        for i in range(len(self.classification_x)):  # 去除只有单个的组群
+            if len(self.classification_x[i]) <= 1 and not must_forward:  # 检测到有单个群组
+                front_reason = classification_reason[i]  # 前原因
+                back_reason = classification_reason[i + 1]  # 后原因
+                if front_reason < back_reason:  # 前原因小于后原因,连接到前面
+                    try:
+                        new_classification_x[-1] += self.classification_x[i]
+                        new_classification_y[-1] += self.classification_y[i]
+                    except BaseException:  # 按道理不应该出现这个情况
+                        new_classification_x.append(self.classification_x[i])
+                        new_classification_y.append(self.classification_y[i])
+                else:
+                    new_classification_x.append(self.classification_x[i])
+                    new_classification_y.append(self.classification_y[i])
+                    must_forward = True
+            else:
+                if not must_forward:
+                    new_classification_x.append(self.classification_x[i])
+                    new_classification_y.append(self.classification_y[i])
+                else:
+                    new_classification_x[-1] += self.classification_x[i]
+                    new_classification_y[-1] += self.classification_y[i]
+                    must_forward = False
+        self.classification_x = new_classification_x
+        self.classification_y = new_classification_y
+        self.have_data_packet = True
+        self.dataframe = pandas.DataFrame((self.x, self.y), index=("x", "y"))
+        self.best_value_core()
+        return self.x, self.y, self.func_name, self.style
+
+
+class ExpBestValue(ExpDataPacket):
+    def best_value_core(self):  # 计算最值和极值点
+        # 使用ya解决了因计算器误差而没计算到的最值,但是同时本不是最值的与最值相近的数字也被当为了最值,所以使用群组击破
+        if not self.have_data_packet:
+            self.data_packet()  # 检查Cul的计算
+        if len(self.classification_x) != 1:  # 没有计算的必要
+            if self.best_r is None:
+                self.best_r = not tkinter.messagebox.askokcancel(
+                    "建议不计算最值", f"{self}的最值计算不精确,函数可能无最值,是否不计算最值"
+                )
+            if not self.best_r:
+                pass
+                return self.max_x, self.max_y, self.min_x, self.min_y
+        y = self.y_real + self.memore_y  # x和y数据对齐(因为是加法,所以y的修改不影响self.__ya)
+        _y = self.y + self.memore_y
+        x = self.x + self.memore_x
+        max_y = max(y)
+        min_y = min(y)
+        max_x = find_x_by_y(x.copy(), y, max_y)
+        min_x = find_x_by_y(x.copy(), y, min_y)
+        # 处理最大值极值点重复
+        max_x = sorted(list(set(max_x)))  # 处理重复
+        groups_list = []
+        last_x = None
+        flat = False
+        can_handle = max_x.copy()  # 可处理列表
+        for i in range(len(max_x)):  # 迭代选择
+            now_x = max_x[i]
+            if last_x is None or abs(now_x - last_x) >= 1:  # 1-连续系数
+                flat = False
+            else:
+                if flat:  # 加入群组
+                    groups_list[-1].append(now_x)
+                else:  # 新键群组
+                    groups_list.append([last_x, now_x])
+                    del can_handle[can_handle.index(last_x)]
+                    flat = True
+                del can_handle[can_handle.index(now_x)]  # 删除可处理列表
+            last_x = now_x
+        for i in groups_list:  # 逐个攻破群组
+            groups_y = []  # 群组中x的y值
+            for x_in_groups in i:
+                num = x.index(x_in_groups)
+                groups_y.append(_y[num])  # 找到对应y值
+            groups_x = find_x_by_y(i, groups_y, max(groups_y))
+            groups_max_x = groups_x[int(len(groups_x) / 2)]
+            can_handle.append(groups_max_x)  # 取中间个
+        self.max_y = max_y
+        self.max_x = can_handle
+        # 处理最小值极值点重复
+        min_x = sorted(list(set(min_x)))  # 处理重复
+        groups_list = []
+        last_x = None
+        flat = False
+        can_handle = min_x.copy()  # 可处理列表
+        for i in range(len(min_x)):  # 迭代选择
+            now_x = min_x[i]
+            if last_x is None or abs(now_x - last_x) >= 1:  # 1-连续系数
+                flat = False
+            else:
+                if flat:  # 加入群组
+                    groups_list[-1].append(now_x)
+                else:  # 新键群组
+                    groups_list.append([last_x, now_x])
+                    del can_handle[can_handle.index(last_x)]
+                    flat = True
+                del can_handle[can_handle.index(now_x)]  # 删除可处理列表
+            last_x = now_x
+        for i in groups_list:  # 逐个攻破群组
+            groups_y = []  # 群组中x的y值
+            for x_in_groups in i:
+                num = x.index(x_in_groups)
+                groups_y.append(_y[num])  # 找到对应y值
+
+            groups_x = find_x_by_y(i, groups_y, min(groups_y))
+            groups_max_x = groups_x[int(len(groups_x) / 2)]
+            can_handle.append(groups_max_x)  # 取中间个
+
+        self.min_y = min_y
+        self.min_x = can_handle
+        return self.max_x, self.max_y, self.min_x, self.min_y
+
+    def best_value(self):
+        return self.max_x, self.max_y, self.min_x, self.min_y
+
+
+class ExpComputing(ExpBestValue):
+
+    def sympy_calculation(self, y_value):  # 利用Sympy解方程
+        try:
+            equation = self.func - float(y_value)
+            result_list = sympy.solve(equation, self.symbol_x)
+            answer = []
+            for x in result_list:
+                self.memore_x.append(x)  # 可能需要修复成float(x)
+                self.memore_y.append(y_value)
+                answer.append(f"y={y_value} -> x={x}")
+            return answer, result_list
+        except BaseException:
+            return [], []
+
+    def gradient_calculation(self, y_value, start, end, max_iter=100, accuracy=0.00001):
+        try:
+            y_value = float(y_value)
+            start = float(start)
+            end = float(end)
+        except BaseException:
+            return "", None
+        try:
+            max_iter = int(max_iter)
+            accuracy = float(accuracy)
+        except BaseException:
+            max_iter = 100
+            accuracy = 0.00001
+        left = start
+        right = end
+        left_history = []
+        right_history = []
+        middle_history = None
+        contraction_direction = 0  # 收缩方向1=a往b,2=b往a,0=未知
+        actual_monotony = 0  # 增or减
+        for i in range(max_iter):
+            if left > right:
+                left, right = right, left  # a是小的数字,b是大的数字,c是中间
+            left_history.append(left)  # 赋值a的回退值
+            right_history.append(right)
+            middle = (left + right) / 2
+            middle_y = self(middle)
+            # 增减预测
+            if abs(middle_y - y_value) < accuracy:  # 数据计算完成
+                break
+            elif middle_y < y_value:  # 预测增还是减:_c移动到y_in需要增还是间
+                future_monotony = 1  # 增
+            else:
+                future_monotony = 0  # 减
+            try:  # 当前是增还是减
+                if middle_history == middle_y:  # 恰好关于了原点对称
+                    pass  # 保持不变
+                elif middle_history < middle_y:
+                    actual_monotony = 1  # 增
+                else:
+                    actual_monotony = 0  # 减
+            except BaseException:
+                contraction_direction = 1
+                actual_monotony = future_monotony
+            middle_history = middle_y
+            # 开始行动
+            if future_monotony == actual_monotony:  # 实际和预测一样,保持相同执行方案
+                if contraction_direction == 1:  # a往b方向收缩
+                    left = middle
+                else:
+                    right = middle
+            else:
+                if contraction_direction == 1:  # 收缩方向相反
+                    left = left_history[-2]
+                    right = middle
+                    contraction_direction = 0
+                else:
+                    left = middle
+                    right = right_history[-2]
+                    contraction_direction = 1
+        else:
+            return "", None
+        self.memore_x.append(middle)
+        self.memore_y.append(y_value)
+        self.memory_answer.append(f"y={y_value} -> x={middle}")
+        print(f"y={y_value} -> x={middle}", middle)
+        return f"y={y_value} -> x={middle}", middle
+
+    def dichotomy(
+        self,
+        y_value,
+        max_iter=100,
+        accuracy=0.0001,
+        best_value_starting_offset=0.1,
+        zero_minimum_distance=0.5,
+        allow_original_value=False,
+        allow_extended_calculations=True,
+        expansion_depth=1000,
+        expansion_limit=0.1,
+        new_area_offset=0.1,
+        secondary_verification=False,
+        secondary_verification_effect=None,
+        return_all=False,
+    ):
+        # y_in输入的参数,k最大迭代数,r_Cul允许使用原来的数值,d精度,ky最值允许偏移量,kx新区间偏移量,cx扩张限制,dx两零点的最小范围,deep扩张深度
+        # H_Cul允许扩展计算,f_On开启二级验证,f二级验证效果
+        if secondary_verification_effect is None:
+            secondary_verification_effect = accuracy
+        try:  # 参数处理
+            allow_original_value = to_bool(allow_original_value)
+            allow_extended_calculations = to_bool(allow_extended_calculations, True)
+            secondary_verification = to_bool(secondary_verification)
+            max_iter = abs(int(max_iter))
+            accuracy = abs(float(accuracy))
+            best_value_starting_offset = abs(float(best_value_starting_offset))
+            new_area_offset = abs(float(new_area_offset))
+            expansion_limit = abs(float(expansion_limit))
+            zero_minimum_distance = abs(float(zero_minimum_distance))
+            expansion_depth = abs(int(expansion_depth))
+            secondary_verification_effect = abs(float(secondary_verification_effect))
+        except BaseException:
+            allow_original_value = False
+            allow_extended_calculations = True
+            secondary_verification = False
+            max_iter = 100
+            accuracy = 0.0001
+            best_value_starting_offset = 0.1
+            new_area_offset = 0.1
+            expansion_limit = 0.5
+            zero_minimum_distance = 0.5
+            expansion_depth = 100
+            secondary_verification_effect = accuracy
+        if not self.have_data_packet:
+            self.data_packet(float)
+        x = self.x + self.memore_x
+        y = self.y + self.memore_x
+        try:
+            y_value = float(y_value)
+        except BaseException:
+            return [], []
+        try:
+            if (
+                y_value < self.min_y - best_value_starting_offset
+                or y_value > self.max_y + best_value_starting_offset
+            ):
+                return [], []  # 返回空值
+            if allow_original_value and y_value in y:  # 如果已经计算过
+                num = y.index(y_value)
+                return x[num]
+        except BaseException:
+            pass
+        iter_interval = [[self.start, self.end]]  # 准备迭代的列表
+        middle_list = []
+        middle_list_deviation = []
+        for interval in iter_interval:
+            left = interval[0]
+            right = interval[1]
+            middle = None
+            no_break = False
+            for i in range(max_iter):  # 限定次数的迭代
+                try:
+                    if left > right:
+                        left, right = right, left  # a是小的数字,b是大的数字,c是中间
+                    if left == right:  # 如果相等,作废
+                        middle = None
+                        break
+                    left_y = self(left) - y_value  # 计算a
+                    right_y = self(right) - y_value  # 计算b
+                    middle = (left + right) / 2  # 计算c
+                    try:
+                        middle_y = self(middle) - y_value  # 计算c
+                    except BaseException:
+                        if expansion_depth > 0:  # 尝试向两边扩张,前提是有deep余额(扩张限制)而且新去见大于cx
+                            if abs(left - (middle - new_area_offset)) > expansion_limit:
+                                # 增加区间(新区间不包括c,增加了一个偏移kx)
+                                iter_interval.append([left, middle - new_area_offset])
+                                expansion_depth -= 1  # 余额减一
+                            if (
+                                abs((middle + new_area_offset) - right)
+                                > expansion_limit
+                            ):
+                                iter_interval.append(
+                                    [middle + new_area_offset, right]
+                                )  # 增加区间
+                                expansion_depth -= 1
+                            middle = None
+                        break
+                    left_zero_c = left_y * middle_y  # a,c之间零点
+                    right_zero_c = right_y * middle_y  # b,c之间零点
+                    if middle_y == 0:  # 如果c就是零点
+                        if expansion_depth > 0:  # 尝试向两边扩张,前提是有deep余额(扩张限制)而且新去见大于cx
+                            if abs(left - (middle - new_area_offset)) > expansion_limit:
+                                # 增加区间(新区间不包括c,增加了一个偏移kx)
+                                iter_interval.append([left, middle - new_area_offset])
+                                expansion_depth -= 1  # 余额减一
+                            if (
+                                abs((middle + new_area_offset) - right)
+                                > expansion_limit
+                            ):
+                                iter_interval.append(
+                                    [middle + new_area_offset, right]
+                                )  # 增加区间
+                                expansion_depth -= 1
+                        break  # 这个区间迭代完成,跳出返回c
+                    elif left_zero_c * right_zero_c == 0:  # a或者b之间有一个是零点
+                        if left_zero_c == 0:  # a是零点
+                            middle = left
+                            if (
+                                expansion_depth > 0
+                                and abs((left + new_area_offset) - right)
+                                > expansion_limit
+                            ):
+                                iter_interval.append([left + new_area_offset, right])
+                                expansion_depth -= 1
+                            break
+                        else:
+                            middle = right  # 同上
+                            if (
+                                expansion_depth > 0
+                                and abs(left - (right - new_area_offset))
+                                > expansion_limit
+                            ):
+                                iter_interval.append([left, right - new_area_offset])
+                                expansion_depth -= 1
+                            break
+                    elif left_zero_c * right_zero_c > 0:  # q和p都有或都没用零点
+                        if (
+                            left_zero_c > 0
+                            and abs(left - right) < zero_minimum_distance
+                        ):  # 如果ab足够小反围,则认为a和b之间不存在零点
+                            if allow_extended_calculations:
+                                # addNews('进入梯度运算')
+                                middle = self.gradient_calculation(
+                                    y_value, left, right
+                                )[1]
+                                if middle is not None:
+                                    break
+                            middle = None
+                            break
+                        iter_interval.append([right, middle])  # 其中一个方向继续迭代,另一个方向加入候选
+                        right = middle
+                    elif left_zero_c < 0:  # 往一个方向收缩,同时另一个方向增加新的区间
+                        if (
+                            expansion_depth > 0
+                            and abs(middle - right) > expansion_limit
+                        ):
+                            iter_interval.append([middle, right])
+                            expansion_depth -= 1
+                        right = middle
+                    elif right_zero_c < 0:  # 同上
+                        if expansion_depth > 0 and abs(left - middle) > expansion_limit:
+                            iter_interval.append([left, middle])
+                            expansion_depth -= 1
+                        left = middle
+                    if abs(left - right) < accuracy:  # a和b足够小,认为找到零点
+                        middle = (left + right) / 2
+                        middle_y = self(middle)
+                        if (
+                            secondary_verification
+                            and abs(y_value - middle_y) > secondary_verification_effect
+                        ):
+                            middle = None
+                        break
+                except BaseException:
+                    break
+            else:  # 证明没有break
+                no_break = True
+            if middle is None:
+                continue  # 去除c不存在的选项
+            if not no_break:
+                middle_list.append(middle)
+            else:
+                middle_list_deviation.append(middle)
+        answer = []
+        for i in middle_list:
+            self.memore_x.append(i)
+            self.memore_y.append(y_value)
+            answer.append(f"y={y_value} -> x={i}")
+        if return_all:
+            for i in middle_list_deviation:
+                answer.append(f"(误差)y={y_value} -> x={i}")
+        self.memory_answer += answer
+        return answer, middle_list
+
+    def calculation(self, x_in):
+        answer = []
+        for i in x_in:
+            try:
+                i = float(i)
+                y = self(i)
+                answer.append(f"x={i} -> y={y}={float(y)}")
+                if i not in self.memore_x:
+                    self.memore_x.append(i)
+                    self.memore_y.append(y)
+            except BaseException:  # 捕捉运算错误
+                continue
+        self.best_value_core()
+        self.dataframe = pandas.DataFrame(
+            (self.x + self.memore_x, self.y + self.memore_y), index=("x", "y")
+        )
+        self.memory_answer += answer
+        return answer
+
+    def derivative(self, x_value, delta_x=0.1, must=False):  # 可导函数求导,不可导函数逼近
+        derivatives = self.derivatives
+        try:
+            delta_x = abs(float(delta_x))
+        except BaseException:
+            delta_x = 0.1
+        try:
+            x_value = float(x_value)
+            if derivatives is not None and not must:  # 导函数法
+                derivative_num = derivatives.evalf(subs={self.symbol_x: x_value})
+                derivative_method = "导函数求值"
+            else:
+                x1 = x_value - delta_x / 2
+                x2 = x_value + delta_x / 2
+                y1 = self(x1)
+                y2 = self(x2)
+                delta_x = y2 - y1
+                derivative_num = delta_x / delta_x
+                derivative_method = "逼近法求值"
+        except BaseException:
+            return None, None
+        answer = f"({derivative_method})x:{x_value} -> {derivative_num}"
+        return answer, derivative_num
+
+
+class ExpProperty(ExpComputing):
+    def parity(self, precision=False):  # 启动round处理
+        if not self.have_data_packet:
+            self.data_packet(float)  # 运行Cul计算
+        if len(self.classification_x) != 1:
+            need_computing = True  # 通过self计算y
+        else:
+            need_computing = False
+        y = self.y.copy()
+        x = self.x.copy()
+        a = self.start
+        b = self.end
+        a = -min([abs(a), abs(b)])
+        b = -a
+        flat = None  # 0-偶函数,1-奇函数
+        for i in range(len(x)):
+            now_x = x[i]  # 正项x
+            if now_x < a or now_x > b:
+                continue  # x不在区间内
+            try:
+                if need_computing:
+                    now_y = self(now_x)
+                else:
+                    now_y = y[i]  # 求得x的y
+                if need_computing:
+                    symmetry_y = self(-now_x)
+                else:
+                    symmetry_y = y[x.index(-now_x)]  # 求得-x的y
+                if precision:
+                    now_y = round(now_y, self.accuracy)
+                    symmetry_y = round(symmetry_y, self.accuracy)
+                if symmetry_y == now_y == 0:
+                    continue
+                elif symmetry_y == now_y:
+                    if flat is None:
+                        flat = 0
+                    elif flat == 1:
+                        raise Exception
+                elif symmetry_y == -now_y:
+                    if flat is None:
+                        flat = 1
+                    elif flat == 0:
+                        raise Exception
+                else:
+                    raise Exception
+            except BaseException:
+                flat = None
+                break
+        return flat, [a, b]
+
+    def monotonic(self):
+        if not self.have_data_packet:
+            self.data_packet(float)  # 运行Cul计算
+        classification_x = self.classification_x.copy()
+        increase_interval = []  # 增区间
+        minus_interval = []  # 减区间
+        interval = []  # 不增不减
+        for i in range(len(classification_x)):
+            x_list = classification_x[i]
+            y_list = classification_x[i]
+            last_x = None
+            last_y = None
+            start_x = None
+            flat = None  # 当前研究反围:0-增区间,1-减区间,2-不增不减
+            for a in range(len(x_list)):
+                now_x = x_list[a]  # 正项x
+                now_y = y_list[a]  # 正项y
+                if start_x is None:
+                    start_x = now_x
+                else:
+                    if last_y > now_y:  # 减区间
+                        if flat is None or flat == 1:  # 减区间
+                            pass
+                        elif flat == 0:  # 增区间
+                            increase_interval.append((start_x, last_x))
+                            start_x = last_x
+                        elif flat == 2:
+                            interval.append((start_x, last_x))
+                            start_x = last_x
+                        flat = 1
+                    elif last_y < now_y:  # 增区间
+                        if flat is None or flat == 0:  # 增区间
+                            pass
+                        elif flat == 1:  # 减区间
+                            minus_interval.append((start_x, last_x))
+                            start_x = last_x
+                        elif flat == 2:
+                            interval.append((start_x, last_x))
+                            start_x = last_x
+                        flat = 0
+                    else:  # 水平区间
+                        if flat is None or flat == 2:
+                            pass
+                        elif flat == 1:  # 减区间
+                            minus_interval.append((start_x, last_x))
+                            start_x = last_x
+                        elif flat == 0:  # 增区间
+                            increase_interval.append((start_x, last_x))
+                            start_x = last_x
+                        flat = 2
+                last_x = now_x
+                last_y = now_y
+            if flat == 2:
+                interval.append((start_x, last_x))
+            elif flat == 1:  # 减区间
+                minus_interval.append((start_x, last_x))
+            elif flat == 0:  # 增区间
+                increase_interval.append((start_x, last_x))
+        return increase_interval, minus_interval, interval
+
+    def property_prediction(
+        self, output_prompt=lambda x: x, return_all=False, accuracy=None
+    ):
+        try:
+            accuracy = float(accuracy)
+        except BaseException:
+            accuracy = None
+        answer = []
+        parity = self.parity()
+        monotonic = self.monotonic()
+        periodic = self.periodic(output_prompt, accuracy)
+        symmetry_axis = self.symmetry_axis(output_prompt, accuracy)
+        symmetry_center = self.symmetry_center(output_prompt, accuracy)
+        if parity[0] == 1:
+            answer.append(f"奇函数 区间:[{parity[1][0]},{parity[1][0]}]")
+        elif parity[0] == 0:
+            answer.append(f"偶函数 区间:[{parity[1][0]},{parity[1][0]}]")
+        for i in monotonic[0]:
+            answer.append(f"增区间:[{i[0]},{i[1]}]")
+        for i in monotonic[1]:
+            answer.append(f"减区间:[{i[0]},{i[1]}]")
+        for i in monotonic[2]:
+            answer.append(f"水平区间:[{i[0]},{i[1]}]")
+        if self.derivatives:
+            answer.append(f"导函数:{self.derivatives}")
+        if periodic[0] is not None:
+            answer.append(f"最小正周期:{periodic[0]}")
+        if symmetry_axis[0] is not None:
+            answer.append(f"对称轴:x={symmetry_axis[0]}")
+        if symmetry_center[0] is not None:
+            answer.append(f"对称中心:{symmetry_center[0]}")
+        if return_all:
+            try:
+                for i in periodic[1][1:]:
+                    answer.append(f"可能的最小正周期:{i}")
+            except BaseException:
+                pass
+            try:
+                for i in symmetry_axis[1][1:]:
+                    answer.append(f"可能的对称轴:{i}")
+            except BaseException:
+                pass
+            try:
+                for i in symmetry_center[1][1:]:
+                    answer.append(f"可能的对称中心:{i}")
+            except BaseException:
+                pass
+
+        return answer
+
+    def periodic(self, output_prompt=lambda x: x, accuracy=None):  # 计算周期
+        if not tkinter.messagebox.askokcancel("提示", f"计算周期需要一定时间,是否执行?(计算过程程序可能无响应)"):
+            return None, []  # 无结果
+        if not self.have_data_packet:
+            self.data_packet(float)
+        possible_cycle_list = []  # 可能的周期
+        start = self.start
+        end = self.end
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = abs(start - end) / 20
+        output_prompt("正在预测可能的周期")
+        while start <= end:
+            try:
+                y = self(start)
+                x_list = self.dichotomy(y)[1]
+                output_prompt("迭代运算...")
+                # print(x_list)
+                possible_cycle = []
+                for o_x in x_list:
+                    a = round(abs(o_x - start), self.accuracy)
+                    if a == 0:
+                        start += span
+                        continue
+                    if a:
+                        possible_cycle.append(round(a, self.accuracy))
+                possible_cycle_list.extend(list(set(possible_cycle)))  # 不是append
+            except BaseException:
+                pass
+            start += span
+
+        possible_cycle = []  # a的可能列表
+        max_count = 0
+        output_prompt("正在筛选结果")
+        for i in list(set(possible_cycle_list)):
+            count = possible_cycle_list.count(i)
+            if count > max_count:
+                possible_cycle = [i]
+                max_count = count
+            elif count == max_count:
+                possible_cycle.append(i)
+        try:
+            possible_cycle.sort()
+            output_prompt("计算完毕")
+            return possible_cycle[0], possible_cycle
+        except BaseException:
+            output_prompt("无周期")
+            return None, []  # 无结果
+
+    def symmetry_axis(self, output_prompt=lambda x: x, accuracy=None):  # 计算对称轴
+        if not tkinter.messagebox.askokcancel("提示", f"计算对称轴需要一定时间,是否执行?(计算过程程序可能无响应)"):
+            return None, []  # 无结果
+        if not self.have_data_packet:
+            self.data_packet()
+        possible_symmetry_axis_list = []  # 可能的对称轴
+        start = self.start
+        end = self.end
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = abs(start - end) / 20
+        output_prompt("正在预测对称轴")
+        while start <= end:
+            try:
+                y = self(start)
+                x_list = self.dichotomy(y)[1]
+                output_prompt("迭代运算...")
+                # print(x_list)
+                possible_symmetry_axis = []
+                for o_x in x_list:
+                    a = (o_x + start) / 2
+                    if a:
+                        possible_symmetry_axis.append(round(a, self.accuracy))
+                possible_symmetry_axis_list.extend(list(set(possible_symmetry_axis)))
+            except BaseException:
+                pass
+            start += span
+
+        possible_symmetry_axis = []  # a的可能列表
+        c = 0
+        output_prompt("正在筛选结果")
+        for i in list(set(possible_symmetry_axis_list)):
+            n_c = possible_symmetry_axis_list.count(i)
+            if n_c > c:
+                possible_symmetry_axis = [i]
+                c = n_c
+            elif n_c == c:
+                possible_symmetry_axis.append(i)
+        try:
+            possible_symmetry_axis.sort()  #
+            output_prompt("计算完毕")
+            return possible_symmetry_axis[0], possible_symmetry_axis
+        except BaseException:
+            output_prompt("无对称轴")
+            return None, []  # 无结果
+
+    def symmetry_center(self, output_prompt=lambda x: x, accuracy=None):  # 计算对称中心
+        if not tkinter.messagebox.askokcancel("提示", f"计算对称中心需要一定时间,是否执行?(计算过程程序可能无响应)"):
+            return None, []  # 无结果
+        if not self.have_data_packet:
+            self.data_packet(float)
+        coordinate_points = []  # 可能的对称轴
+        start = self.start
+        end = self.end
+        output_prompt("正在计算坐标点")
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = 1
+        while start <= end:
+            try:
+                y = self(start)
+                x = start
+                coordinate_points.append((x, y))
+            except BaseException:
+                pass
+            start += span
+        possible_center_list = []
+
+        output_prompt("正在预测对称中心")
+        for i in coordinate_points:
+            for o in coordinate_points:
+                x = round((i[0] + o[0]) / 2, self.accuracy)
+                y = round((i[1] + o[1]) / 2, self.accuracy)
+                if i == o:
+                    continue
+                possible_center_list.append((x, y))
+        possible_center = []  # a的可能列表
+        max_count = 0
+        output_prompt("正在筛选结果")
+        for i in list(set(possible_center_list)):
+            count = possible_center_list.count(i)
+            if count > max_count:
+                possible_center = [i]
+                max_count = count
+            elif count == max_count:
+                possible_center.append(i)
+        try:
+            if max_count < 5:
+                raise Exception
+            output_prompt("计算完毕")
+            possible_center.sort()  #
+            return possible_center[int(len(possible_center) / 2)], possible_center
+        except BaseException:
+            output_prompt("无对称中心")
+            return None, []  # 无结果
+
+
+class ExpCheck(ExpFuncInit):
+    def check_monotonic(
+        self, parameters, output_prompt=lambda x: x, accuracy=None
+    ):  # 检查单调性
+        result = True  # 预测结果
+        try:
+            parameters = parameters.split(",")
+            start = float(parameters[0])
+            end = float(parameters[1])
+            flat = float(parameters[2])  # 当前研究反围:0-增区间,1-减区间,2-不增不减
+        except BaseException:
+            return False, ""
+        if start > end:
+            start, end = end, start
+        last_y = None
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = self.span
+        while start <= end:
+            try:
+                output_prompt("迭代运算...")
+                now_y = round(self(start), self.accuracy)
+            except BaseException:
+                start += span
+                continue
+            if last_y is None:
+                continue
+            if flat == 0 and last_y > now_y:  # 增区间,o_y不小于y
+                result = False
+                break
+            elif flat == 1 and last_y < now_y:  # 减小区间,o_y不小于y
+                result = False
+                break
+            elif flat == 2 and last_y != now_y:
+                result = False
+                break
+            last_y = now_y
+            start += span
+
+        monotonic_key = {0: "单调递增", 1: "单调递减", 2: "平行"}
+        result_key = {True: "成立", False: "不成立"}
+        return (
+            result,
+            f"{self}在[{parameters[0]},{parameters[1]}]{monotonic_key[flat]}{result_key[result]}",
+        )
+
+    def check_periodic(
+        self, parameters, output_prompt=lambda x: x, accuracy=None
+    ):  # 检查周期性
+        result = True
+        try:
+            parameters = float(parameters)
+        except BaseException:
+            return False, ""
+        start = self.start
+        end = self.end
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = self.span
+        while start <= end:
+            try:
+                output_prompt("迭代运算...")
+                now_y = round(self(start), self.accuracy)
+                last_y = round(self(start + parameters), self.accuracy)
+                if now_y != last_y:
+                    result = False
+            except BaseException:
+                pass
+            start += span
+        result_key = {True: "是", False: "不是"}
+        return result, f"{self}的周期{result_key[result]}{parameters}"
+
+    def check_symmetry_axis(
+        self, parameters, output_prompt=lambda x: x, accuracy=None
+    ):  # 检查对称轴
+        result = True
+        try:
+            parameters = 2 * float(parameters)
+        except BaseException:
+            return False, ""
+        start = self.start
+        end = self.end
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = self.span
+        while start <= end:
+            try:
+                output_prompt("迭代运算...")
+                now_y = round(self(start), self.accuracy)
+                last_y = round(self(parameters - start), self.accuracy)
+                if now_y != last_y:
+                    result = False
+            except BaseException:
+                pass
+            start += span
+        result_key = {True: "是", False: "不是"}
+        return result, f"{self}的对称轴{result_key[result]}{parameters}"
+
+    def check_symmetry_center(
+        self, parameters_input, output_prompt=lambda x: x, accuracy=None
+    ):  # 检查对称中心
+        result = True
+        try:
+            parameters = []
+            for i in parameters_input.split(","):
+                parameters.append(float(i))
+        except BaseException:
+            return False, ""
+        start = self.start
+        end = self.end
+        if accuracy is not None:
+            span = accuracy
+        else:
+            span = self.span
+        while start <= end:
+            try:
+                output_prompt("迭代运算...")
+                now_y = round(self(start), self.accuracy)
+                last_y = round(self(2 * parameters[0] - start), self.accuracy)
+                if round((now_y + last_y) / 2, self.accuracy) != parameters[1]:
+                    result = False
+            except BaseException:
+                pass
+            start += span
+        result_key = {True: "是", False: "不是"}
+        return result, f"{self}的对称中心{result_key[result]}{parameters}"
+
+
+class ExpMemory(ExpFuncInit):
+    def hide_or_show(self):  # 记忆数据显示和隐藏
+        if self.have_prediction:
+            if tkinter.messagebox.askokcancel("提示", f"是否显示{self}的记忆数据?"):
+                # addNews('记忆显示完毕')
+                self.have_prediction = False
+        else:
+            if tkinter.messagebox.askokcancel("提示", f"是否隐藏{self}的记忆数据?"):
+                # addNews('记忆隐藏完毕')
+                self.have_prediction = True
+
+    def clean_memory(self):
+        self.memore_x = []
+        self.memore_y = []
+        self.memory_answer = []
+
+    def get_memory(self):
+        if self.have_prediction:
+            return [], []
+        return self.memore_x, self.memore_y
+
+
+class ExpFuncSon:
+    def __init__(
+        self, func, style, start=-10, end=10, span=0.1, accuracy=2, a_default=1
+    ):
+        self.symbol_x = sympy.Symbol("x")
+        named_domain = {
+            "a": a_default,
+            "x": self.symbol_x,
+            "Pi": sympy.pi,
+            "e": sympy.E,
+            "log": sympy.log,
+            "sin": sympy.sin,
+            "cos": sympy.cos,
+            "tan": sympy.tan,
+            "cot": lambda x: 1 / sympy.tan(x),
+            "csc": lambda x: 1 / sympy.sin(x),
+            "sec": lambda x: 1 / sympy.cos(x),
+            "sinh": sympy.sinh,
+            "cosh": sympy.cosh,
+            "tanh": sympy.tanh,
+            "asin": sympy.asin,
+            "acos": sympy.acos,
+            "atan": sympy.atan,
+            "abs": abs,
+        }  # 这个是函数命名域
+        self.func = eval(func.replace(" ", ""), named_domain)  # 函数解析式
+        self.func_str = func.replace(" ", "")
+        # 函数基本信息
+        self.func_name = f"y={func} a={a_default}"  # 这个是函数名字
+        self.style = style  # 绘制样式
+        # 数据辨析
+        try:
+            start = float(start)
+            end = float(end)
+            if start > end:  # 使用float确保输入是数字,否则诱发ValueError
+                start, end = end, start
+            span = abs(float(span))
+            start = (start // span) * span  # 确保start可以恰好被kd整除
+            end = (end // span + 1) * span
+            accuracy = abs(int(accuracy))
+            if accuracy >= 3:
+                accuracy = 3
+        except ValueError:
+            start, end, span, accuracy = -10, 10, 0.1, 2  # 保底设置
+        # 基本数据存储
+        self.accuracy = accuracy
+        self.start = start
+        self.end = end
+        self.span = span
+
+        # x和y数据存储
+        self.x = []
+        self.y = []
+        self.y_real = []
+        self.classification_x = [[]]
+        self.classification_y = [[]]
+
+        self.have_data_packet = False
+
+    def __call__(self, x):
+        return self.func.evalf(subs={self.symbol_x: x})
+
+    def __str__(self):
+        return f"{self.func_name} {self.start, self.end, self.span}"
+
+    def data_packet(self, number_type=float):
+        if self.have_data_packet:
+            return self.x, self.y, self.func_name, self.style
+        # 混合存储
+        self.y = []
+        self.y_real = []
+        self.x = []
+        self.classification_x = [[]]
+        self.classification_y = [[]]
+        classification_reason = [100]
+        last_y = None
+        last_monotonic = None  # 单调性 0-增,1-减
+        now_monotonic = 1
+        try:
+            now_x = int(self.start)
+            while now_x <= int(self.end):  # 因为range不接受小数
+                group_score = 0
+                balance = 1
+                try:
+                    accuracy_x = round(now_x, self.accuracy)
+                    now_y = number_type(self(accuracy_x))  # 数字处理方案
+                    accuracy_y = round(now_y, self.accuracy)
+                    if last_y is not None and last_y > now_y:
+                        now_monotonic = 1
+                    elif last_y is not None and last_y < now_y:
+                        now_monotonic = 0
+                    elif last_y is not None and last_y == now_y:
+                        try:
+                            middle_y = self(round(accuracy_x - 0.5 * self.span))
+                            if middle_y == last_y == now_y:  # 真实平衡
+                                balance = 2
+                            elif (
+                                abs(middle_y - last_y) >= 10 * self.span
+                                or abs(middle_y - now_y) >= 10 * self.span
+                            ):
+                                balance = 3
+                                group_score += 5
+                        except BaseException:
+                            balance = 4
+                            group_score += 9
+                        now_monotonic = 2
+                    if last_y is not None and last_monotonic != now_monotonic:
+                        if (last_y * now_y) < 0:
+                            group_score += 5
+                        elif abs(last_y - now_y) >= (10 * self.span):
+                            group_score += 5
+                        if group_score >= 5 and (now_monotonic != 2 or balance != 2):
+                            classification_reason.append(group_score)
+                            self.classification_x.append([])
+                            self.classification_y.append([])
+                    last_monotonic = now_monotonic
+                    self.x.append(accuracy_x)  # 四舍五入减少计算量
+                    self.y.append(now_y)  # 不四舍五入
+                    self.y_real.append(accuracy_y)  # 四舍五入(用于求解最值)
+                    self.classification_x[-1].append(accuracy_x)
+                    self.classification_y[-1].append(now_y)
+                    last_y = now_y
+                except BaseException:
+                    classification_reason.append(0)
+                    self.classification_x.append([])
+                    self.classification_y.append([])
+                now_x += self.span
+        except (TypeError, IndexError, ValueError):
+            pass
+        new_classification_x = []
+        new_classification_y = []
+        classification_reason.append(99)
+        must_forward = False
+        for i in range(len(self.classification_x)):  # 去除只有单个的组群
+            if len(self.classification_x[i]) <= 1 and not must_forward:  # 检测到有单个群组
+                front_reason = classification_reason[i]  # 前原因
+                back_reason = classification_reason[i + 1]  # 后原因
+                if front_reason < back_reason:  # 前原因小于后原因,连接到前面
+                    try:
+                        new_classification_x[-1] += self.classification_x[i]
+                        new_classification_y[-1] += self.classification_y[i]
+                    except BaseException:  # 按道理不应该出现这个情况
+                        new_classification_x.append(self.classification_x[i])
+                        new_classification_y.append(self.classification_y[i])
+                else:
+                    new_classification_x.append(self.classification_x[i])
+                    new_classification_y.append(self.classification_y[i])
+                    must_forward = True
+            else:
+                if not must_forward:
+                    new_classification_x.append(self.classification_x[i])
+                    new_classification_y.append(self.classification_y[i])
+                else:
+                    new_classification_x[-1] += self.classification_x[i]
+                    new_classification_y[-1] += self.classification_y[i]
+                    must_forward = False
+        self.classification_x = new_classification_x
+        self.classification_y = new_classification_y
+        self.have_data_packet = True
+        return self.x, self.y, self.func_name, self.style
+
+    def get_plot_data(self):
+        if not self.have_data_packet:
+            self.data_packet()
+        return (
+            self.classification_x,
+            self.classification_y,
+            self.func_name,
+            self.style,
+        )

部分文件因为文件数量过多而无法显示