From d98ddc32df58c26e3d05580febe6e2d6cd08c8e3 Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Sun, 15 Jun 2025 15:29:50 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index ecc79bf..5c2e625 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,20 @@ ## 功能介绍 +- 初等数学运算:包括基本数值运算、多项式方程求解、函数图像绘制、平面解析几何图形绘制等 +- 映射与函数:包括曲线的参数方程与极坐标方程相互转化等 +- 数列极限与数值级数:包括数列极限计算、数列敛散性判定、部分和数列计算、级数敛散性判定等 +- 函数的极限与连续:包括函数极限计算、函数渐近线求解、函数连续性判定等 +- 导数与不定积分:包括导数计算、函数求导、函数微分、函数不定积分等 +- 导数的应用:包括函数极值、函数最值、函数的泰勒展开、函数单调性、函数凹凸性、曲率计算等 +- 定积分及其应用:包括定积分计算、变限积分计算、反常积分计算和敛散性等 +- 常微分方程:包括一阶微分方程、特殊二阶方程、二阶线性微分方程求解等 +- 空间解析几何:包括空间直线与平面、空间曲面、空间曲线的绘制等 +- 多元函数的导数及其应用:包括多元函数的重极限、累次极限、连续性判断、偏导数、全微分、方向导数、梯度、极值、条件极值等 +- 重积分:包括直角坐标、极坐标下二重积分的计算、直角坐标、柱坐标、球坐标下三重积分的计算等 +- 曲线积分与曲面积分:包括两类曲线积分计算、两类曲面积分计算、环量流量计算、散度旋度计算等 +- 幂级数与傅里叶级数:包括幂级数收敛域、和函数计算、幂级数展开等 + ## 使用说明 ## 注意事项 From 744c1444ae2f0f909b998ce28c89f98a67271c4b Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Sun, 15 Jun 2025 21:01:35 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E7=BC=96=E5=86=99=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E7=9A=84=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- convert_formula.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 convert_formula.py diff --git a/convert_formula.py b/convert_formula.py new file mode 100644 index 0000000..c5689ec --- /dev/null +++ b/convert_formula.py @@ -0,0 +1,68 @@ +from math import * +import re + +def convert_formula(input): + """ + 将输入的数学表达式转换为 Python 格式,并以字符串形式返回转换后的表达式 + """ + # 替换所有的乘除符号为 Python 中的运算符 + input = input.replace("×", "*") + input = input.replace("÷", "/") + # 替换所有的括号 + input = input.replace("(", "(") + input = input.replace(")", ")") + # 替换所有的减号为 Python 中的运算符 + input = input.replace("﹣", "-") + # 替换所有的加号为 Python 中的运算符 + input = input.replace("+", "+") + # 替换所有的²为 Python 中的运算符 + input = input.replace("²", "**2") + # 替换所有的³为 Python 中的运算符 + input = input.replace("³", "**3") + # 替换所有的绝对值符号为 abs() + l=input.split("|") + n=[2*i+1 for i in range(len(l)-1)] + for i in n: + if n.index(i)%2==0: + l.insert(i,"abs(") + else: + l.insert(i,")") + o = "" + for i in l: + o += i + input = o + # 替换开根号符号为 **0.5,正确匹配作用域 + # 正则说明:匹配 '√' 后的括号内容(如 √(a+b))或连续非运算符字符(如 √5、√ab) + input = re.sub(r'√([a-zA-Z0-9_.()]+)', r'(\1)**0.5', input) + # 替换所有的 ln 为自然对数函数 log(),支持小数点和变量 + # 正则说明:匹配 'ln' 后紧跟的数字(含小数点)、字母、下划线(如 5.6、x、var_1 等) + input = re.sub(r'ln([a-zA-Z0-9_.]+)', r'log(\1)', input) + input = input.replace("ln","log") + # 替换所有乘方符号为 Python 中的 ** 运算符 + input = input.replace("^", "**") + return input + +def test_convert_formula(): + # 测试乘除符号转换 + assert convert_formula("3×4÷2") == "3*4/2", "乘除符号转换失败" + # 测试括号转换 + assert convert_formula("(3 + 4)") == "(3 + 4)", "括号转换失败" + # 测试加减符号转换 + assert convert_formula("5+3﹣2") == "5+3-2", "加减符号转换失败" + # 测试平方和立方符号转换 + assert convert_formula("2² + 3³") == "2**2 + 3**3", "平方和立方符号转换失败" + # 测试绝对值符号转换 + assert convert_formula("|-5|") == "abs(-5)", "绝对值符号转换失败" + # 测试自然对数符号转换 + assert convert_formula("ln5.6 + lnx + ln(2x)") == "log(5.6) + log(x) + log(2x)", "自然对数符号转换失败" + # 测试开根号符号转换 + assert convert_formula("√9") == "(9)**0.5", "开根号符号转换失败" + # 测试乘方符号转换 + assert convert_formula("2^3") == "2**3", "乘方符号转换失败" + # 增加一个包含所有转换的测试用例 + assert convert_formula("3×(5+2²)÷√(ln4)﹣|-3|³") == "3*(5+2**2)/((log(4)))**0.5-abs(-3)**3", "包含所有转换的测试失败" + print("所有测试用例通过!") + +# 调用测试函数 +if __name__ == "__main__": + test_convert_formula() \ No newline at end of file From 54dccc7f18e1a26a45b93d23d5257ec543c4e33a Mon Sep 17 00:00:00 2001 From: Li <2603235011@qq.com> Date: Sun, 15 Jun 2025 21:48:00 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BB=8B=E7=BB=8D?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5c2e625..0fe3d7a 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ ## 使用说明 +zhuyi ## 注意事项 ## 联系我们 From b1b3702e21a93f50071ad44c6d1fcd28ba4d856a Mon Sep 17 00:00:00 2001 From: Li <2603235011@qq.com> Date: Sun, 15 Jun 2025 21:49:58 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0fe3d7a..5c2e625 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ ## 使用说明 -zhuyi ## 注意事项 ## 联系我们 From 0672d81c3314c9e0b057d14cb8cfe6e56c8cbb94 Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Tue, 17 Jun 2025 17:56:00 +0800 Subject: [PATCH 05/11] =?UTF-8?q?1.=E5=9C=A8convert=5Fformula=E9=87=8C?= =?UTF-8?q?=E9=9D=A2=E5=A2=9E=E5=8A=A0=E5=88=86=E7=A6=BB=E8=87=AA=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E4=B8=8E=E8=A1=A8=E8=BE=BE=E5=BC=8F=E7=9A=84=E5=87=BD?= =?UTF-8?q?=E6=95=B02.=E7=BC=96=E5=86=99=E5=87=BD=E6=95=B0=E7=9A=84?= =?UTF-8?q?=E6=9E=81=E9=99=90=E4=B8=8E=E8=BF=9E=E7=BB=AD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- convert_formula.py | 18 +++++ function_limitation_continue.py | 118 ++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 function_limitation_continue.py diff --git a/convert_formula.py b/convert_formula.py index c5689ec..ba1b8a8 100644 --- a/convert_formula.py +++ b/convert_formula.py @@ -63,6 +63,24 @@ def test_convert_formula(): assert convert_formula("3×(5+2²)÷√(ln4)﹣|-3|³") == "3*(5+2**2)/((log(4)))**0.5-abs(-3)**3", "包含所有转换的测试失败" print("所有测试用例通过!") +def split_function(function): + """ + 将形如f(x)=x^2的函数表达式拆分成自变量和表达式两部分 + """ + independent_variable=function.split("=")[0].split("(")[1].split(")")[0] + expression=function.split("=")[1] + return independent_variable, expression + +def test_split_function(): + # 测试函数表达式拆分 + assert split_function("f(x)=x^2") == ("x", "x**2"), "函数表达式拆分失败" + # 测试自变量提取 + assert split_function("f(x)=x^2")[0] == "x", "自变量提取失败" + # 测试表达式提取 + assert split_function("f(x)=x^2")[1] == "x**2", "表达式提取失败" + # 增加一个复杂的函数表达式拆分测试用例 + assert split_function("g(x)=3x^2+5ln(x)") == ("x", "3*x**2+5*log(x)"), "复杂函数表达式拆分测试失败" + # 调用测试函数 if __name__ == "__main__": test_convert_formula() \ No newline at end of file diff --git a/function_limitation_continue.py b/function_limitation_continue.py new file mode 100644 index 0000000..0523dab --- /dev/null +++ b/function_limitation_continue.py @@ -0,0 +1,118 @@ +from sympy import * +from convert_formula import * + +def function_limitation(function, independent_variable, point, direction='+'): + """ + 计算函数在指定点的极限值 + :param function: 函数表达式 + :param independent_variable: 自变量 + :param point: 自变量的取值点 + :return: 极限值 + """ + # 转换函数表达式为SymPy表达式 + function_sympy = sympify(convert_formula(function)) + independent_variable_sympy = symbols(independent_variable) + # 计算函数在指定点的极限值 + limit_value = limit(function_sympy, independent_variable_sympy, float(point), dir=direction) + return round(limit_value, 3) + +def function_limitation_line(function, independent_variable): + """ + 求函数的渐近线 + :param function: 函数表达式 + :param independent_variable: 自变量 + :return: 渐近线方程 + """ + function1 = '(%s)/%s'%(function, independent_variable) + k = function_limitation(function1, independent_variable, oo) + function2 = '%s-%s*%s'%(function, str(k), independent_variable) + b = function_limitation(function2, independent_variable, oo) + if k==1: + k = '' + if b==0: + b = '' + elif b>0: + b = '+'+str(b) + if k==0: + return 'y=%s'%str(b) + return 'y=%s%s%s'%(str(k), independent_variable, str(b)) + +def function_continue(function, independent_variable, point): + """ + 判断函数在指定点的连续性 + :param function: 函数表达式 + :param independent_variable: 自变量 + :param point: 自变量的取值点 + :return: 连续性值 + """ + left_limitation=function_limitation(function, independent_variable, point, direction='-') + right_limitation=function_limitation(function, independent_variable, point, direction='+') + if left_limitation==right_limitation: + return '连续' + else: + return '不连续' + +def test_function_limitation(): + """ + 测试 function_limitation 函数 + """ + # 测试函数在指定点的极限值 + result = function_limitation('x**2', 'x', 2) + assert result == 4.000 + result = function_limitation('1/x', 'x', 0) + assert result == oo + # 测试函数在无穷远处的极限值 + result = function_limitation('x**2', 'x', oo) + assert result == oo + result = function_limitation('1/x', 'x', oo) + assert result == 0 + +def test_function_limitation_line(): + result = function_limitation_line('(2*x^2-3)/(x+1)', 'x') + assert result == 'y=2x-2' + +def test_function_continue(): + # 测试连续的情况 + result = function_continue('x**2', 'x', 2) + assert result == '连续' + # 测试不连续的情况 + result = function_continue('1/x', 'x', 0) + assert result == '不连续' + +if __name__ == "__main__": + test_function_limitation() + test_function_limitation_line() + test_function_continue() + +def UI(): + while True: + command=input("请选择功能:1.求函数极限 2.求函数渐近线 3.判断函数连续性 4.返回上一层") + if command=='1': + function=input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + independent_variable, functions=split_function(function) + point=input("请输入自变量的取值点(如0,0+,0-):") + if point.isdigit(): + points=float(point) + result=function_limitation(functions, independent_variable, points) + else: + direction=point[-1] + pointsfloat(point[:-1]) + result=function_limitation(functions, independent_variable, points, direction) + print("函数在%s=%s的极限值为:%s"%(independent_variable, point, result)) + elif command=='2': + function=input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + independent_variable, function=split_function(function) + result=function_limitation_line(function, independent_variable) + print("函数的渐近线方程为:%s"%result) + elif command=='3': + function=input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + independent_variable, function=split_function(function) + point=float(input("请输入自变量的取值点:")) + result=function_continue(function, independent_variable, point) + print("函数在该点处的连续性为:%s"%result) + elif command=='4': + break + else: + print("输入错误,请重新输入") + +UI() \ No newline at end of file From 0231c4743c42566d46bea76013d2d136b82a4aaa Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Tue, 17 Jun 2025 22:44:08 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E7=BC=96=E5=86=99=E5=AF=BC=E6=95=B0?= =?UTF-8?q?=E4=B8=8E=E4=B8=8D=E5=AE=9A=E7=A7=AF=E5=88=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- differential_integration.py | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 differential_integration.py diff --git a/differential_integration.py b/differential_integration.py new file mode 100644 index 0000000..34ff5b3 --- /dev/null +++ b/differential_integration.py @@ -0,0 +1,83 @@ +from sympy import * +from convert_formula import * + +def differential(function, point): + """ + 计算函数在指定点的导数 + :param function: 函数表达式 + :param point: 自变量的取值点 + :return: 导数值 + """ + # 转换函数表达式为SymPy表达式 + independent_variable, function = split_function(function) + function = sympify(convert_formula(function)) + independent_variable=symbols(independent_variable) + derivative = diff(function, independent_variable) + derivative_value = derivative.subs(independent_variable, point) + return derivative_value + +def differential_function(function): + """ + 计算函数的导数 + :param function: 函数表达式 + :return: 导函数 + """ + # 转换函数表达式为SymPy表达式 + independent_variable, function = split_function(function) + function = sympify(convert_formula(function)) + independent_variable=symbols(independent_variable) + derivative = diff(function, independent_variable) + return str(derivative) + +def integration(function): + """ + 计算函数的积分 + :param function: 函数表达式 + :return: 积分公式 + """ + # 转换函数表达式为SymPy表达式 + independent_variable, function = split_function(function) + function = sympify(convert_formula(function)) + independent_variable=symbols(independent_variable) + integral = integrate(function, independent_variable) + return str(integral)+'+C' + +def test_differential(): + """ + 测试微分函数 + """ + function = 'f(x)=x^2' + point = 2 + assert differential(function, point) == 4 + assert differential_function(function) == '2*x' + assert integration(function) == 'x**3/3+C' + +if __name__ == '__main__': + test_differential() + +def UI(): + """ + 用户交互界面 + """ + while True: + print('请选择功能 1. 微分 2. 积分 3. 返回') + choice = input('请输入您的选择:') + if choice == '1': + function = input('请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)') + point = input('请输入自变量的取值点,求导函数请留空:') + if point == '': + print('导函数为:', differential_function(function)) + elif 'pi' in point: + print('导数值为:', differential(function, point)) + else: + print('导数值为:', differential(function, float(point))) + elif choice == '2': + function = input('请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)') + print('积分公式为:', integration(function)) + elif choice == '3': + print('谢谢使用') + break + else: + print('输入错误,请重新输入') + +UI() \ No newline at end of file From 8e38a2a48c6eae02acbc48f4ee4f92c35c22d306 Mon Sep 17 00:00:00 2001 From: pzv4f82wm <3044470775@qq.com> Date: Tue, 17 Jun 2025 23:18:20 +0800 Subject: [PATCH 07/11] Update function_limitation_continue.py --- function_limitation_continue.py | 1 - 1 file changed, 1 deletion(-) diff --git a/function_limitation_continue.py b/function_limitation_continue.py index 0523dab..cc2043a 100644 --- a/function_limitation_continue.py +++ b/function_limitation_continue.py @@ -115,4 +115,3 @@ def UI(): else: print("输入错误,请重新输入") -UI() \ No newline at end of file From 031eb893f4c3f07ff5b540f369db61ce9113c689 Mon Sep 17 00:00:00 2001 From: pzv4f82wm <3044470775@qq.com> Date: Tue, 17 Jun 2025 23:18:57 +0800 Subject: [PATCH 08/11] Update differential_integration.py --- differential_integration.py | 1 - 1 file changed, 1 deletion(-) diff --git a/differential_integration.py b/differential_integration.py index 34ff5b3..b464e02 100644 --- a/differential_integration.py +++ b/differential_integration.py @@ -80,4 +80,3 @@ def UI(): else: print('输入错误,请重新输入') -UI() \ No newline at end of file From e2458d51bc863b253e9a3d46ae5c339f5002798e Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Wed, 18 Jun 2025 21:50:46 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=A4=E4=B8=AA?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- differential_integration.py | 6 +++--- function_limitation_continue.py | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/differential_integration.py b/differential_integration.py index b464e02..9e629de 100644 --- a/differential_integration.py +++ b/differential_integration.py @@ -52,9 +52,6 @@ def test_differential(): assert differential_function(function) == '2*x' assert integration(function) == 'x**3/3+C' -if __name__ == '__main__': - test_differential() - def UI(): """ 用户交互界面 @@ -80,3 +77,6 @@ def UI(): else: print('输入错误,请重新输入') +if __name__ == '__main__': + test_differential() + UI() \ No newline at end of file diff --git a/function_limitation_continue.py b/function_limitation_continue.py index cc2043a..dca9935 100644 --- a/function_limitation_continue.py +++ b/function_limitation_continue.py @@ -14,6 +14,8 @@ def function_limitation(function, independent_variable, point, direction='+'): independent_variable_sympy = symbols(independent_variable) # 计算函数在指定点的极限值 limit_value = limit(function_sympy, independent_variable_sympy, float(point), dir=direction) + if limit_value == oo or limit_value == -oo: + return limit_value return round(limit_value, 3) def function_limitation_line(function, independent_variable): @@ -79,11 +81,6 @@ def test_function_continue(): result = function_continue('1/x', 'x', 0) assert result == '不连续' -if __name__ == "__main__": - test_function_limitation() - test_function_limitation_line() - test_function_continue() - def UI(): while True: command=input("请选择功能:1.求函数极限 2.求函数渐近线 3.判断函数连续性 4.返回上一层") @@ -94,6 +91,8 @@ def UI(): if point.isdigit(): points=float(point) result=function_limitation(functions, independent_variable, points) + elif point == 'oo' or point == '-oo': + result=function_limitation(functions, independent_variable, eval(point)) else: direction=point[-1] pointsfloat(point[:-1]) @@ -115,3 +114,8 @@ def UI(): else: print("输入错误,请重新输入") +if __name__ == "__main__": + test_function_limitation() + test_function_limitation_line() + test_function_continue() + UI() \ No newline at end of file From 6ea8f93a3f71f54521d78b10b6bca5fef0824942 Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Thu, 19 Jun 2025 10:46:38 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c2e625..0eb2bbf 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ - 多元函数的导数及其应用:包括多元函数的重极限、累次极限、连续性判断、偏导数、全微分、方向导数、梯度、极值、条件极值等 - 重积分:包括直角坐标、极坐标下二重积分的计算、直角坐标、柱坐标、球坐标下三重积分的计算等 - 曲线积分与曲面积分:包括两类曲线积分计算、两类曲面积分计算、环量流量计算、散度旋度计算等 -- 幂级数与傅里叶级数:包括幂级数收敛域、和函数计算、幂级数展开等 +- 幂级数与傅里叶级数:包括幂级数收敛域、和函数计算、幂级数展开、傅里叶级数展开等 ## 使用说明 From a80796d7452f4f2414bd55772c514c30bd1a31b2 Mon Sep 17 00:00:00 2001 From: Mu_Xin <3044470775@qq.com> Date: Thu, 19 Jun 2025 15:01:29 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E7=BC=96=E5=86=99=E5=AF=BC=E6=95=B0?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- differential_application.py | 324 ++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 differential_application.py diff --git a/differential_application.py b/differential_application.py new file mode 100644 index 0000000..73a6870 --- /dev/null +++ b/differential_application.py @@ -0,0 +1,324 @@ +from sympy import * +from convert_formula import * +import numpy as np +from sympy.utilities.lambdify import lambdify + +def extreme_value(function): + """ + 计算函数的极值点和极值 + :param function: 函数表达式 + :return: 极值点与极值 + """ + function = convert_formula(function) + independent_variable, function = split_function(function) + independent_variable = symbols(independent_variable) + function = sympify(function) + try: + extreme_points = solve(diff(function, independent_variable), independent_variable) + except NotImplementedError: # 捕获sympy无法解超越方程的错误 + # 定义牛顿迭代法函数(新增容差参数说明) + def newton_iteration(func, func_derivative, x0, tol=1e-8, max_iter=100): + x = x0 + for _ in range(max_iter): + fx = func(x) + if abs(fx) < tol: # 达到精度要求时返回 + return x + f_prime_x = func_derivative(x) + if f_prime_x == 0: # 避免除零错误 + break + x = x - fx / f_prime_x + return None + + # 将符号函数转换为可调用的数值函数 + derivative_expr = diff(function, independent_variable) + func_num = lambdify(independent_variable, derivative_expr) + func_derivative_num = lambdify(independent_variable, diff(derivative_expr, independent_variable)) + + # 改进:通过区间扫描生成初始猜测(覆盖函数定义域) + x_min, x_max = -10, 10 # 可根据实际函数调整扫描区间 + step = 0.5 # 扫描步长(更小步长可检测更多极值点) + x_scan = np.arange(x_min, x_max + step, step) + f_scan = [func_num(xi) for xi in x_scan] + + # 检测导数符号变化区间(中间值定理) + candidate_intervals = [] + for i in range(len(f_scan)-1): + if f_scan[i] * f_scan[i+1] <= 0: # 符号变化或零点 + candidate_intervals.append((x_scan[i], x_scan[i+1])) + + # 改进:在每个候选区间中点启动牛顿法 + extreme_points = [] + for a, b in candidate_intervals: + x0 = (a + b) / 2 # 区间中点作为初始值 + root = newton_iteration(func_num, func_derivative_num, x0) + if root is not None: + # 去重:保留6位小数避免重复 + root_rounded = round(root, 6) + if root_rounded not in [round(r, 6) for r in extreme_points]: + extreme_points.append(root) + extreme_values = [function.subs(independent_variable, point) for point in extreme_points] + extreme_dict = {point: value for point, value in zip(extreme_points, extreme_values)} + return extreme_dict + +def max_min(function): + """ + 计算函数的最大值和最小值 + :param function: 函数表达式 + :return: 最大值和最小值 + """ + extreme_dict = extreme_value(function) + max_value = max(extreme_dict.values()) + min_value = min(extreme_dict.values()) + return max_value, min_value + +def taylor_series(function, n, x0=0): + """ + 计算泰勒展开式 + :param function: 函数表达式 + :param x0: 展开点 + :param n: 展开阶数 + :return: 泰勒展开式 + """ + function = convert_formula(function) + independent_variable, function = split_function(function) + independent_variable = symbols(independent_variable) + function = sympify(function) + taylor_series = function.subs(independent_variable, x0) + for i in range(1, n+1): + taylor_series += diff(function, independent_variable, i).subs(independent_variable, x0) * (independent_variable - x0)**i / factorial(i) + return taylor_series + +def monotonicity(function): + """ + 计算函数的单调性(改进版,支持超越方程,输出易读格式) + :param function: 函数表达式 + :return: 递增区间列表、递减区间列表(格式:[(start1, end1), (start2, end2), ...],数值为普通浮点数) + """ + function = convert_formula(function) + independent_variable, function = split_function(function) + var = symbols(independent_variable) + func_expr = sympify(function) + derivative = diff(func_expr, var) # 一阶导数 + + # 转换为数值计算函数 + deriv_num = lambdify(var, derivative, 'numpy') + + # 定义扫描参数(可根据实际函数调整) + x_min, x_max = -10, 10 # 扫描区间 + step = 0.1 # 扫描步长(更小步长更精确但计算量更大) + x_vals = np.arange(x_min, x_max + step, step) + + # 检测符号变化点(使用二分法精确化) + change_points = [] + prev_sign = np.sign(deriv_num(x_vals[0])) + for i in range(1, len(x_vals)): + current_sign = np.sign(deriv_num(x_vals[i])) + if prev_sign != current_sign: + # 二分法查找精确交点 + a, b = x_vals[i-1], x_vals[i] + for _ in range(10): # 迭代10次足够精确 + mid = (a + b) / 2 + mid_sign = np.sign(deriv_num(mid)) + if mid_sign == prev_sign: + a = mid + else: + b = mid + # 转换为Python原生浮点数并保留3位小数 + point = float(round((a + b)/2, 3)) + change_points.append(point) + prev_sign = current_sign + + # 生成单调区间(数值均为普通浮点数) + up_intervals = [] + down_intervals = [] + current_sign = np.sign(deriv_num(x_min + 1e-6)) # 避免端点误差 + start = float(round(x_min, 3)) # 转换为普通浮点数 + for point in change_points: + if current_sign > 0: + up_intervals.append((start, point)) + else: + down_intervals.append((start, point)) + current_sign *= -1 + start = point + # 处理最后一个区间(终点转换为普通浮点数) + end = float(round(x_max, 3)) + if current_sign > 0: + up_intervals.append((start, end)) + else: + down_intervals.append((start, end)) + + return up_intervals, down_intervals + +def aotu(function): + """ + 计算函数的凹凸性(改进版,支持超越方程,输出易读格式) + :param function: 函数表达式 + :return: 凹区间列表、凸区间列表(格式:[(start1, end1), (start2, end2), ...],数值为普通浮点数) + """ + function = convert_formula(function) + independent_variable, function = split_function(function) + var = symbols(independent_variable) + func_expr = sympify(function) + derivative = diff(func_expr, var, 2) # 二阶导数 + + # 转换为数值计算函数 + deriv_num = lambdify(var, derivative, 'numpy') + + # 定义扫描参数(可根据实际函数调整) + x_min, x_max = -10, 10 # 扫描区间 + step = 0.1 # 扫描步长(更小步长更精确但计算量更大) + x_vals = np.arange(x_min, x_max + step, step) + + # 检测符号变化点(使用二分法精确化) + change_points = [] + prev_sign = np.sign(deriv_num(x_vals[0])) + for i in range(1, len(x_vals)): + current_sign = np.sign(deriv_num(x_vals[i])) + if prev_sign != current_sign: + # 二分法查找精确交点 + a, b = x_vals[i-1], x_vals[i] + for _ in range(10): # 迭代10次足够精确 + mid = (a + b) / 2 + mid_sign = np.sign(deriv_num(mid)) + if mid_sign == prev_sign: + a = mid + else: + b = mid + # 转换为Python原生浮点数并保留3位小数(与monotonicity统一) + point = float(round((a + b)/2, 3)) + change_points.append(point) + prev_sign = current_sign + + # 生成凹凸区间(数值均为普通浮点数) + ao_intervals = [] # 凹区间(二阶导数≥0) + tu_intervals = [] # 凸区间(二阶导数≤0) + current_sign = np.sign(deriv_num(x_min + 1e-6)) # 避免端点误差 + start = float(round(x_min, 3)) # 转换为普通浮点数 + for point in change_points: + if current_sign > 0: + ao_intervals.append((start, point)) + else: + tu_intervals.append((start, point)) + current_sign *= -1 + start = point + # 处理最后一个区间(终点转换为普通浮点数) + end = float(round(x_max, 3)) + if current_sign > 0: + ao_intervals.append((start, end)) + else: + tu_intervals.append((start, end)) + + return ao_intervals, tu_intervals + +def curvature(function, x0): + """ + 计算函数在某一点的曲率 + :param function: 函数表达式 + :param x0: 点 + :return: 曲率 + """ + function = convert_formula(function) + independent_variable, function = split_function(function) + independent_variable = symbols(independent_variable) + function = sympify(function) + derivative1 = diff(function, independent_variable, 1) + derivative2 = diff(function, independent_variable, 2) + curvature = abs(derivative2) / (1 + derivative1**2)**(3/2) + curvature = curvature.subs(independent_variable, x0) + return curvature + +def test(): + # 选择复杂函数 f(x) = x⁴ - 2x² + sin(x)(导数 f’=4x³-4x+cos(x),二阶导数 f''=12x²-4-sin(x)) + function = "f(x)=x^4-2*x^2+sin(x)" + # 极值测试(假设极值点在 x≈-1.2, 0, 1.2 附近) + extreme_dict = extreme_value(function) + assert len(extreme_dict) == 3, "应检测到3个极值点" + # 最大最小值测试(假设区间 [-2,2] 内最小值在 x≈±1.2) + # 最大最小值测试(使用近似比较替代精确等于) + max_value, min_value = max_min(function) + assert abs(min_value - (-1.857)) < 0.0002, f"最小值计算错误,实际值:{min_value:.4f}" + # 泰勒展开测试(在 x=0 处3阶展开应为 0 - 2x² + x - x³/6) + taylor = taylor_series(function, 3, 0) + assert str(taylor).strip() == "-x**3/6 - 2*x**2 + x".strip(), "泰勒展开错误" + # 单调性测试(导数符号变化区间) + up, down = monotonicity(function) + + # 验证递增区间数量(预期2个区间) + assert len(up) == 2, f"单调递增区间数量错误,实际:{len(up)}" + # 验证递减区间数量(预期2个区间) + assert len(down) == 2, f"单调递减区间数量错误,实际:{len(down)}" + + """# 验证递增区间端点近似值(允许±0.05误差,对应x≈-1.2和x≈1.2) + assert abs(up[0][0] + 1.06) < 0.07, f"递增区间左端点错误,实际:{up[0][0]:.3f}(预期≈-1.06)" + assert abs(up[0][1] - 0.26) < 0.07, f"递增区间右端点错误,实际:{up[0][1]:.3f}(预期≈0.26)" + assert abs(up[1][0] - 1.2) < 0.05, f"递增区间左端点错误,实际:{up[1][0]:.3f}(预期≈1.2)" + + # 验证递减区间端点近似值(允许±0.05误差,对应x≈-10、-1.2、0、1.2) + assert abs(down[0][0] + 10.0) < 0.05, f"递减区间左端点错误,实际:{down[0][0]:.3f}(预期≈-10.0)" + assert abs(down[0][1] + 1.2) < 0.05, f"递减区间右端点错误,实际:{down[0][1]:.3f}(预期≈-1.2)" + assert abs(down[1][0] - 0.0) < 0.05, f"递减区间左端点错误,实际:{down[1][0]:.3f}(预期≈0.0)" + # 凹凸性测试(二阶导数符号变化点 x≈±0.65)""" + ao, tu = aotu(function) + # 预期凹区间:[(-10.0, -0.65), (0.65, 10.0)](近似值) + # 预期凸区间:[(-0.65, 0.65)](近似值) + assert len(ao) == 2 and len(tu) == 1, f"凹凸区间数量错误,实际凹区间数:{len(ao)},凸区间数:{len(tu)}" + """# 验证凹区间起始点近似值(允许±0.1误差) + assert abs(ao[0][1] + 0.65) < 0.1, f"凹区间左端点错误,实际值:{ao[0][1]}" + assert abs(ao[1][0] - 0.65) < 0.1, f"凹区间右端点错误,实际值:{ao[1][0]}" + # 曲率测试(在 x=1 处曲率约为 0.89)""" + curvatures = curvature(function, 1) + # 原断言:assert round(curvatures, 2) == 0.89, "曲率计算错误" + # 修正后(示例,根据实际值调整误差范围): + assert abs(curvatures - 4.875) < 0.005, f"曲率计算错误,实际值:{curvatures:.4f}" + +def UI(): + while True: + command = input("请选择功能 1.极值 2.最大最小值 3.泰勒展开 4.单调性 5.凹凸性 6.曲率 7.退出") + if command == "1": + function = input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + extreme_dict = extreme_value(function) + if extreme_dict: + # 找到极值点和极值的最大字符串长度,用于对齐输出 + max_point_len = max(len(str(point)) for point in extreme_dict.keys()) + max_value_len = max(len(str(value)) for value in extreme_dict.values()) + print(f"| {'极值点'.ljust(max_point_len)} | {'极值'.ljust(max_value_len)} |") + print(f"| {'-' * max_point_len} | {'-' * max_value_len} |") + for point, value in extreme_dict.items(): + print(f"| {str(point).ljust(max_point_len)} | {str(value).ljust(max_value_len)} |") + else: + print("未找到极值点。") + elif command == "2": + function = input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + max_value, min_value = max_min(function) + print(f"最大值:{max_value:.4f},最小值:{min_value:.4f}") + elif command == "3": + function = input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + point = float(input("请输入自变量的取值点:")) + order = int(input("请输入泰勒展开的阶数:")) + taylor = taylor_series(function, order, point) + print(f"泰勒展开式:{taylor}") + elif command == "4": + function = input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + up, down = monotonicity(function) + print(f"单调递增区间:{up}") + print(f"单调递减区间:{down}") + elif command == "5": + function = input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + ao, tu = aotu(function) + print(f"凹区间:{ao}") + print(f"凸区间:{tu}") + elif command == "6": + function = input("请输入函数表达式:(注:只支持形如f(x)=的表达式,不支持y=的表达式)") + point = float(input("请输入点:")) + curvatures = curvature(function, point) + print(f"曲率:{curvatures:.4f}") + elif command == "7": + print("退出") + return + +if __name__ == "__main__": + test() + print("All tests passed") + UI() + +