1 条题解

  • 0
    @ 2025-4-16 22:34:15

    题意分析

    这段代码实现了一个符号求导系统,可以对输入的数学表达式进行求导运算。支持的运算包括:

    • 基本运算:加法(+)、减法(-)、乘法(*)、除法(/)。
    • 函数运算:自然对数(ln)。
    • 变量:仅支持变量 x
    • 常数:如 5-3.14 等数字。

    输入:一个合法的数学表达式字符串(如 x+5ln(x))。
    输出:该表达式的导数(如 1+0(1)/(x))。

    解题思路

    1. 表达式解析

      • 使用递归下降法(Recursive Descent Parsing)分解表达式。
      • 根据运算符优先级(+/- < *// < (/ln)拆分表达式。
    2. 求导规则

      • 常数:导数为 0
      • 变量 x:导数为 1
      • 加法/减法(u±v)' = u' ± v'
      • 乘法(u*v)' = u'*v + u*v'
      • 除法(u/v)' = (u'*v - u*v') / v^2
      • 自然对数(ln(u))' = u' / u
    3. 优化输出

      • 合并连续的 +-(如 1+-21-2)。
      • 去除多余的括号(如 ((x))x)。

    代码

    #include <iostream>
    #include <string>
    #include <stack>
    #include <cctype>
    using namespace std;
    
    // 辅助函数:判断是否为数字
    bool is_number(const string &s) {
        if (s.empty()) return false;
        size_t i = 0;
        if (s[0] == '-' || s[0] == '+') i++;
        bool has_digit = false;
        bool has_dot = false;
        for (; i < s.size(); i++) {
            if (s[i] == '.') {
                if (has_dot) return false;
                has_dot = true;
            } else if (!isdigit(s[i])) {
                return false;
            } else {
                has_digit = true;
            }
        }
        return has_digit;
    }
    
    // 主求导函数
    string derive(const string &expr) {
        // 基础情况
        if (expr == "x") return "1";
        if (is_number(expr)) return "0";
        
        // 处理括号表达式
        if (expr.size() >= 3 && expr[0] == '(' && expr.back() == ')') {
            string inner = expr.substr(1, expr.size()-2);
            
            // 检查是否是ln函数
            if (inner.size() > 3 && inner.substr(0, 3) == "ln(" && inner.back() == ')') {
                string arg = inner.substr(3, inner.size()-4);
                string d_arg = derive(arg);
                return "(" + d_arg + ")/(" + arg + ")";
            }
            
            // 解析运算符
            int op_pos = -1;
            int paren_level = 0;
            for (int i = 0; i < inner.size(); ++i) {
                char c = inner[i];
                if (c == '(') paren_level++;
                else if (c == ')') paren_level--;
                else if (paren_level == 0 && (c == '+' || c == '-' || c == '*' || c == '/')) {
                    op_pos = i;
                    break;
                }
            }
            
            if (op_pos != -1) {
                char op = inner[op_pos];
                string left = inner.substr(0, op_pos);
                string right = inner.substr(op_pos+1);
                string d_left = derive(left);
                string d_right = derive(right);
                
                switch (op) {
                    case '+': return "(" + d_left + "+" + d_right + ")";
                    case '-': return "(" + d_left + "-" + d_right + ")";
                    case '*': return "(" + d_left + "*" + right + "+" + left + "*" + d_right + ")";
                    case '/': return "(" + d_left + "*" + right + "-" + left + "*" + d_right + ")/" + right + "^2";
                }
            }
        }
        
        return "0"; // 默认情况
    }
    
    int main() {
        string line;
        while (getline(cin, line)) {
            cout << derive(line) << endl;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    468
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    8
    已通过
    1
    上传者