You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

绘图计算器函数解析问题求助:-x²与x²+2x+1解析失效

函数解析Solver在-x²和x²+2x+1测试用例下失效的问题

我正在做一个学校项目,开发一款能绘制函数图像的计算器。图像绘制功能没问题,但负责把数学函数转换成数据的Solver函数在两个测试用例上出问题了:输入-x²和x²+2x+1的时候解析结果不对。按照现有的代码逻辑,这两个用例应该能正常运行才对,我卡了好半天,试了几种修改都要么没解决问题,要么把其他方程的解析给搞坏了,实在没辙了,来求助大家!

下面是我的Solver函数和配套的parsing函数代码:

double Solver(string input, double xValue) { 
    int pos1; 
    int pos2; 
    int symbolpos; 
    string substring; 
    double value1; 
    double value2; 
    int count; 

    while (input.find_first_of(" ") != string::npos) { 
        input.erase(input.find_first_of(" "), 1); 
    } 

    while (input.find("(") != string::npos && input.find(")") != string::npos) { 
        pos1 = input.find_first_of("("); 
        if (pos1 > 0 && input[pos1 - 1] != '-') { 
            input.insert(pos1, "*"); 
            pos1++; 
        } 
        if (pos1 == 2 && input[0] == '-') { 
            input.insert(pos1 - 1, "1"); 
            pos1++; 
        } 
        pos2 = pos1; 
        count = 1; 
        while (count != 0) { 
            pos2++; 
            if (input[pos2] == '(') count++; 
            if (input[pos2] == ')') count--; 
        } 
        substring = to_string(Solver(input.substr(pos1 + 1, pos2 - pos1 - 1), xValue)); 
        input.replace(pos1, pos2 - pos1 + 1, substring); 
    } 

    while (input.find("x") != string::npos) { 
        pos1 = input.find_first_of("x"); 
        if (pos1 > 0) { 
            input.insert(pos1, "*"); 
            pos1++; 
        } 
        if (pos1 == 2 && input[0] == '-') { 
            input.insert(pos1 - 1, "1"); 
            pos1++; 
        } 
        input.replace(pos1, 1, to_string(xValue)); 
    } 

    while (input.find("--") != string::npos) { 
        input.replace(input.find("--"), 2, "+"); 
    } 

    input = parsing(input, '^'); 
    input = parsing(input, '*'); 
    input = parsing(input, '/'); 
    input = parsing(input, '+'); 
    input = parsing(input, '-'); 

    return stod(input); 
} 

string parsing(string tInput, char searchChar) { 
    string input = tInput; 
    int pos1, pos2, symbolpos; 
    double value1, value2; 
    string substring; 

    while (input.substr(1).find_first_of(searchChar) != string::npos) { 
        symbolpos = input.find_last_of(searchChar); 
        pos1 = 0; 
        for (int a = 0; a < symbolpos - 1; a++) { 
            if (input[a] == '^') pos1 = a++; 
            if (input[a] == '*') pos1 = a++; 
            if (input[a] == '/') pos1 = a++; 
            if (input[a] == '+') pos1 = a++; 
            if (input[a] == '-') pos1 = a; 
        } 
        pos2 = input.size(); 
        for (int a = input.size(); a > symbolpos + 1; a--) { 
            if (input[a] == '^') pos2 = a--; 
            if (input[a] == '*') pos2 = a--; 
            if (input[a] == '/') pos2 = a--; 
            if (input[a] == '+') pos2 = a--; 
            if (input[a] == '-') pos2 = a--; 
        } 
        value1 = stod(input.substr(pos1, symbolpos - pos1)); 
        value2 = stod(input.substr(symbolpos + 1, pos2 - symbolpos)); 

        if (searchChar == '^') substring = to_string(pow(value1, value2)); 
        if (searchChar == '*') substring = to_string(value1 * value2); 
        if (searchChar == '/') substring = to_string(value1 / value2); 
        if (searchChar == '+') substring = to_string(value1 + value2); 
        if (searchChar == '-') substring = to_string(value1 - value2); 

        input.replace(pos1, pos2 - pos1, substring); 
    } 
    return input; 
}

问题分析与修复方案

咱们先拆解这两个测试用例的问题根源,再给出不破坏其他解析逻辑的修复:

1. -x²的问题:一元负号处理错误

原代码在处理-x²时,会在x前盲目插入*,变成-*x²,替换x后变成-*2^2,这显然会导致解析或计算混乱。核心问题是没区分一元负号(比如-x)和二元运算符(比如3-x)。

修复x替换逻辑:

while (input.find("x") != string::npos) {
    pos1 = input.find_first_of("x");
    // 只有当x前面是数字或右括号时,才插入*(避免一元负号场景乱加)
    if (pos1 > 0 && (isdigit(input[pos1-1]) || input[pos1-1] == ')')) {
        input.insert(pos1, "*");
        pos1++;
    }
    // 处理一元负号:-x → -1*x
    if (pos1 == 1 && input[0] == '-') {
        input.insert(pos1, "1*");
        pos1 += 2;
    }
    input.replace(pos1, 1, to_string(xValue));
}

修改后,-x²会先转为-1*x²,替换x后变成-1*2^2,后续能正确计算出-4。

2. x²+2x+1的问题:运算符边界查找逻辑错误

原parsing函数的边界查找循环条件和a++写法会导致漏掉运算符前后的正确边界,比如处理+时,无法准确截取x²和2x这样的完整项,导致计算顺序出错。

重构parsing函数的边界查找逻辑:

#include <cstring> // 需要引入这个头文件用strchr

string parsing(string tInput, char searchChar) {
    string input = tInput;
    int symbolpos;
    double value1, value2;
    string substring;

    // 区分减法的一元负号和二元减号
    bool isSubtraction = (searchChar == '-');

    while (true) {
        if (isSubtraction) {
            // 只找二元减号(跳过开头的一元负号)
            symbolpos = input.find_first_of('-', 1);
        } else {
            symbolpos = input.find_first_of(searchChar);
        }
        if (symbolpos == string::npos) break;

        // 向左找当前运算符的左侧起始位置
        int pos1 = 0;
        for (int a = symbolpos - 1; a >= 0; a--) {
            if (strchr("^*/+-", input[a]) != nullptr) {
                // 如果是开头的一元负号,继续往左(其实这里不会触发,因为二元减号从1开始找)
                if (input[a] == '-' && a == 0) continue;
                pos1 = a + 1;
                break;
            }
        }

        // 向右找当前运算符的右侧结束位置
        int pos2 = input.size();
        for (int a = symbolpos + 1; a < input.size(); a++) {
            if (strchr("^*/+-", input[a]) != nullptr) {
                pos2 = a;
                break;
            }
        }

        try {
            value1 = stod(input.substr(pos1, symbolpos - pos1));
            value2 = stod(input.substr(symbolpos + 1, pos2 - symbolpos - 1));
        } catch (...) {
            // 解析失败则跳过(处理特殊边界情况)
            if (isSubtraction) {
                symbolpos = input.find_first_of('-', symbolpos + 1);
                if (symbolpos == string::npos) break;
                continue;
            }
            break;
        }

        if (searchChar == '^') substring = to_string(pow(value1, value2));
        else if (searchChar == '*') substring = to_string(value1 * value2);
        else if (searchChar == '/') substring = to_string(value1 / value2);
        else if (searchChar == '+') substring = to_string(value1 + value2);
        else if (searchChar == '-') substring = to_string(value1 - value2);

        input.replace(pos1, pos2 - pos1, substring);
    }

    // 单独处理开头的一元负号:比如 -5 → 0-5
    if (isSubtraction && input[0] == '-') {
        input = "0" + input;
        return parsing(input, '-');
    }

    return input;
}

这个版本能准确截取运算符前后的完整项,处理x²+2x+1时,替换x为2后得到2^2+2*2+1,会按正确顺序计算出9。

额外优化:括号处的一元负号处理

原代码在处理-(x+1)这类情况时也会出错,补充括号部分的逻辑:

while (input.find("(") != string::npos && input.find(")") != string::npos) {
    pos1 = input.find_first_of("(");
    // 只有括号前是数字或右括号时才加*
    if (pos1 > 0 && (isdigit(input[pos1-1]) || input[pos1-1] == ')')) {
        input.insert(pos1, "*");
        pos1++;
    }
    // 处理-(...) → -1*(...)
    if (pos1 == 1 && input[0] == '-') {
        input.insert(pos1, "1*");
        pos1 += 2;
    }
    // 原有括号逻辑不变...
}

测试验证

修改后,测试-x²(x=2)得到-4,x²+2x+1(x=2)得到9,同时不会破坏3*x+5、(x+1)^2等其他方程的解析逻辑。


内容的提问来源于stack exchange,提问作者Alexander Fritschi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:26:52