高中函数一把梭

54 1

import numpy as np
import sympy as sp
from scipy.optimize import minimize_scalar
from sympy import Sum, Product, Symbol, oo, Abs, floor, ceiling
import re

class FunctionExtremaAnalyzer:
    def __init__(self):
        self.x = sp.symbols('x')
        self.k = sp.symbols('k')  # 求和/连乘索引变量
        
    def parse_input_range(self, range_input):
        """处理输入范围,默认返回(-oo, oo)"""
        if not range_input.strip():
            return -oo, oo
        
        try:
            # 处理各种输入格式:[a,b], (a,b), a b, a,b
            range_input = re.sub(r'[\[\]()]', '', range_input)
            if ',' in range_input:
                x_min, x_max = map(sp.sympify, range_input.split(','))
            else:
                x_min, x_max = map(sp.sympify, range_input.split())
            return x_min, x_max
        except:
            raise ValueError("范围输入格式无效,请使用[min,max]或留空表示全实数范围")

    def preprocess_expression(self, expr_str):
        """预处理表达式字符串,将abs替换为Abs"""
        # 替换所有abs(...)为Abs(...)
        expr_str = re.sub(r'\babs\s*\(', 'Abs(', expr_str)
        return expr_str

    def analyze_extrema(self):
        print("高级函数极值分析工具")
        print("支持功能:三角函数、指数对数、Σ求和、Π连乘、绝对值(Abs)")
        print("示例输入:")
        print("  sin(x)*Sum(k**2, (k, 1, floor(Abs(x)))) + Abs(x-1)")
        print("  Product(cos(k*x), (k, 1, 5)) * exp(-Abs(x))")
        
        while True:
            try:
                # 输入函数表达式
                expr_str = input("\n请输入函数表达式(变量用x表示): ")
                expr_str = self.preprocess_expression(expr_str)
                
                # 转换为Sympy表达式
                expr = sp.sympify(expr_str, locals={
                    'Sum': Sum, 'sum': Sum, 'Σ': Sum,
                    'Product': Product, 'prod': Product, 'Π': Product,
                    'Abs': Abs, 'abs': Abs,
                    'floor': floor, 'ceiling': ceiling
                })
                
                # 输入范围(默认全实数范围)
                range_input = input("请输入范围 [min, max](留空表示全实数范围R): ")
                x_min, x_max = self.parse_input_range(range_input)
                
                # 分析表达式特性
                has_sum_prod = expr.has(Sum) or expr.has(Product)
                has_abs_floor = expr.has(Abs) or expr.has(floor) or expr.has(ceiling)
                
                # 选择分析方法
                if has_sum_prod or has_abs_floor:
                    extrema = self.symbolic_analysis(expr, x_min, x_max)
                else:
                    extrema = self.numeric_analysis(expr, x_min, x_max)
                
                # 显示结果
                self.display_results(extrema)
                
                # 询问是否继续
                if input("\n是否继续分析其他函数?(y/n): ").lower() != 'y':
                    break
                    
            except Exception as e:
                print(f"错误: {str(e)}")
                print("请检查输入并重试")

    def symbolic_analysis(self, expr, x_min, x_max):
        """符号分析方法,处理含Σ、Π、Abs等的复杂表达式"""
        print("\n使用符号分析方法...")
        
        # 处理无限范围
        if x_min == -oo or x_max == oo:
            print("警告:符号计算需要有限范围,自动设置为[-10,10]")
            x_min, x_max = -10, 10
        
        # 计算一阶导数
        deriv = sp.diff(expr, self.x)
        print(f"导数表达式: {deriv}")
        
        # 求临界点(导数=0的点)
        critical_points = []
        try:
            solutions = sp.solve(deriv, self.x)
            critical_points = [sol.evalf() for sol in solutions if sol.is_real]
        except:
            print("无法解析求解临界点,尝试数值方法")
        
        # 添加不可导点(Abs、floor等函数的转折点)
        nondiff_points = self.find_nondifferentiable_points(expr, x_min, x_max)
        critical_points.extend(nondiff_points)
        
        # 添加边界点
        evaluation_points = critical_points.copy()
        evaluation_points.extend([x_min, x_max])
        
        # 计算所有候选点的函数值
        extrema = {'min': None, 'max': None}
        for point in evaluation_points:
            try:
                val = expr.subs(self.x, point).evalf()
                if not val.is_finite:
                    continue
                
                val = float(val)
                point = float(point)
                
                # 更新最小值
                if extrema['min'] is None or val < extrema['min'][1]:
                    extrema['min'] = (point, val)
                
                # 更新最大值
                if extrema['max'] is None or val > extrema['max'][1]:
                    extrema['max'] = (point, val)
                    
            except:
                continue
        
        return extrema

    def find_nondifferentiable_points(self, expr, x_min, x_max):
        """查找不可导点(如Abs的零点,floor/ceiling的不连续点)"""
        points = []
        
        # 查找Abs的参数为零的点
        for abs_expr in expr.find(Abs):
            arg = abs_expr.args[0]
            try:
                solution = sp.solve(arg, self.x)
                sol = solution[0].evalf()
                if x_min <= sol <= x_max:
                    points.append(sol)
            except:
                pass
        
        # 查找floor/ceiling的不连续点(整数点)
        for fn in [floor, ceiling]:
            for fn_expr in expr.find(fn):
                arg = fn_expr.args[0]
                # 在范围内查找所有使arg为整数的x
                try:
                    # 估算可能的不连续点范围
                    k_min = int(np.ceil(float(arg.subs(self.x, x_min))))
                    k_max = int(np.floor(float(arg.subs(self.x, x_max))))
                    
                    for k in range(k_min, k_max+1):
                        try:
                            sol = sp.solve(arg - k, self.x)
                            if sol:
                                s = sol[0].evalf()
                                if x_min <= s <= x_max:
                                    points.append(s)
                        except:
                            pass
                except:
                    pass
        
        return points

    def numeric_analysis(self, expr, x_min, x_max):
        """数值分析方法,用于常规函数"""
        print("\n使用数值分析方法...")
        
        # 转换为数值函数
        f = sp.lambdify(self.x, expr, modules=[
            'numpy', 
            {
                'sin': np.sin, 'cos': np.cos, 'tan': np.tan,
                'exp': np.exp, 'log': np.log, 'sqrt': np.sqrt,
                'Abs': np.abs, 'abs': np.abs,
                'floor': np.floor, 'ceiling': np.ceil
            }
        ])
        
        # 处理无限范围
        if x_min == -oo:
            x_min = -1e6
            print("自动设置下限为-1e6")
        if x_max == oo:
            x_max = 1e6
            print("自动设置上限为1e6")
        
        # 寻找极值
        extrema = {'min': None, 'max': None}
        
        # 寻找最小值
        try:
            res_min = minimize_scalar(f, bounds=(float(x_min), float(x_max)), method='bounded')
            extrema['min'] = (res_min.x, res_min.fun)
        except:
            pass
        
        # 寻找最大值(通过最小化-f)
        try:
            res_max = minimize_scalar(lambda x: -f(x), bounds=(float(x_min), float(x_max)), method='bounded')
            extrema['max'] = (res_max.x, -res_max.fun)
        except:
            pass
        
        # 检查边界点
        try:
            f_min = f(float(x_min))
            if extrema['min'] is None or f_min < extrema['min'][1]:
                extrema['min'] = (float(x_min), f_min)
            if extrema['max'] is None or f_min > extrema['max'][1]:
                extrema['max'] = (float(x_min), f_min)
        except:
            pass
        
        try:
            f_max = f(float(x_max))
            if extrema['min'] is None or f_max < extrema['min'][1]:
                extrema['min'] = (float(x_max), f_max)
            if extrema['max'] is None or f_max > extrema['max'][1]:
                extrema['max'] = (float(x_max), f_max)
        except:
            pass
        
        return extrema

    def display_results(self, extrema):
        """显示极值结果"""
        print("\n分析结果:")
        
        if extrema['min'] is not None:
            print(f"最小值: f({extrema['min'][0]:.6f}) = {extrema['min'][1]:.6f}")
        else:
            print("未找到最小值")
            
        if extrema['max'] is not None:
            print(f"最大值: f({extrema['max'][0]:.6f}) = {extrema['max'][1]:.6f}")
        else:
            print("未找到最大值")

if __name__ == "__main__":
    analyzer = FunctionExtremaAnalyzer()
    analyzer.analyze_extrema()

按理来说是可以求导的

乐于研究网络安全 个人主页
最新回复 ( 1 )
  • 2
    0
    滚来滚去……~(~o ̄▽ ̄)~o 。。。滚来滚去……o~(_△_o~) ~。。。
  • 游客
    3

    您需要登录后才可以回帖

    登录 注册

发新帖