JavaScript编写字符串数值计算功能遇到问题求指导
代码存在的问题
- 缺少自定义函数
getSubstringIndex的定义:代码中处理百分号逻辑时反复调用了该方法,但没有给出实现,运行时会直接抛出未定义错误 - 未处理特殊运算符映射:你在字符校验规则中允许了
x(乘号)和^(幂运算)两个符号,但没有做替换转换,6 x 2、6^2这类表达式直接传给eval会触发语法错误 - 不支持隐式乘法:类似
2(3)的书写方式JS原生不识别,没有做转换处理的话这类表达式运行会报错 - 未过滤输入中的
=符号:如果输入表达式本身包含等号(比如测试用例2 + 2 - 1 = 3 + 2),处理后传入eval的表达式依然存在等号,会触发语法错误 - 没有异常捕获逻辑:如果表达式存在语法问题,
eval会直接抛出错误终止程序,而不是按预期返回空结果
修正后的完整代码
// 补充缺失的getSubstringIndex方法 const getSubstringIndex = (str, substr, occurrence) => { let pos = 0; for (let i = 0; i < occurrence; i++) { pos = str.indexOf(substr, pos + 1); if (pos === -1) break; } return pos; } const toCalculate = (string) => { // 先移除输入本身带的等号 let calculate = "=" + string.toLowerCase().replace(/=/g, ""); if ( isFinite( calculate.replace( /\=|\+|\-|\*|\/|\÷|\%|\(|\)|\,|\ |math.|pow|sqrt|round|floor|ceiling|ceil|pi|π|euler|absolute|abs|exp|logarithm|log|random|rand|rng|x|\^/g, "" ) ) ) { calculate = calculate .replace(/ /g, "") .replace(/÷/g, "/") .replace(/x/g, "*") // 新增x转乘号逻辑 .replace(/\^/g, "**") // 新增^转幂运算逻辑 // 新增隐式乘法转换:数字/右括号后接左括号时自动补乘号 .replace(/(\d|\))\(/g, '$1*(') .replace(/power|pow/g, "Math.pow") .replace(/sqrt|squareroot/g, "Math.sqrt") .replace(/round/g, "Math.round") .replace(/floor/g, "Math.floor") .replace(/ceiling|ceil/g, "Math.ceil") .replace(/pi|π/g, "Math.PI") .replace(/euler/g, "Math.E") .replace(/absolute|abs/g, "Math.abs") .replace(/exp/g, "Math.exp") .replace(/logarithm|log/g, "Math.log") .replace(/random|rand|rng/g, "Math.random()"); if (calculate.replace(/[^%]/g, "").length > 0) { for (let i = 0; i < calculate.replace(/[^%]/g, "").length; i++) { while ( (calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "+" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "-" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "*" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "/" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "(" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == ")" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "," || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "^" || calculate[getSubstringIndex(calculate, "%", i + 1) + 1] == "x" || getSubstringIndex(calculate, "%", i + 1) + 1 == calculate.length) && calculate.replace(/[^%]/g, "").length > 0 ) { for (let j = getSubstringIndex(calculate, "%", i + 1); j > -1; j--) { if ( calculate[j] == "=" || calculate[j] == "+" || calculate[j] == "-" || calculate[j] == "*" || calculate[j] == "/" || calculate[j] == "(" || calculate[j] == ")" || calculate[j] == "," || calculate[j] == "^" || calculate[j] == "x" ) { calculate = calculate.substring(0, j + 1) + calculate.substring(j + 1, getSubstringIndex(calculate, "%", i + 1)) / 100 + calculate.substring(getSubstringIndex(calculate, "%", i + 1) + 1, calculate.length); break; } } } } } calculate = calculate.replace(/=/g, ""); // 新增异常捕获,避免eval报错阻塞程序运行 try { const res = eval(calculate) if (isFinite(res)) return string + ' = ' + res; } catch (e) { return undefined } } }; // 测试用例运行结果 console.log('math 0:', toCalculate('2 ÷ 2 + 1 - 2 + 22')); // 2 ÷ 2 + 1 - 2 + 22 = 22 console.log('math 1:', toCalculate('2 + 2 - 1')); // 2 + 2 - 1 = 3 console.log('math 2:', toCalculate('4 ÷ 2 + 9')); // 4 ÷ 2 + 9 = 11 console.log('math 3:', toCalculate('888 + 88 + 8 + 8 + 8')); // 888 + 88 + 8 + 8 + 8 = 1000 console.log('math 4:', toCalculate('(7+7) * (7 + (1/7))')); // (7+7) * (7 + (1/7)) = 100 console.log('math 5:', toCalculate('2 + 2 - 1 = 3 + 2')); // undefined(表达式本身不合法) console.log('math 6:', toCalculate('6 - 1 x 0 + 2 ÷ 2')); // 6 - 1 x 0 + 2 ÷ 2 = 7 console.log('math 7:', toCalculate('6^2 ÷ 2(3) + 4')); // 6^2 ÷ 2(3) + 4 = 58 console.log('math 8:', toCalculate('6 - 1 x 0 + 2 ÷ 2')); // 6 - 1 x 0 + 2 ÷ 2 = 7 console.log('math 9:', toCalculate('6 x 2')); // 6 x 2 = 12
内容的提问来源于stack exchange,提问作者user15949323
相关产品推荐
相关产品推荐

