如何从通用字符串中提取合规算术表达式并支持小数、指数运算
完整实现方案
1. 核心匹配正则
const exprReg = /(?:\d+\.?\d*|\.\d+)?(?:[+\-*/^()]|(?<=\d|\))\()+(?:\d+\.?\d*|\.\d+)/g;
该正则支持整数、小数(包含.123这类省略整数位的写法)、^指数运算符、34(5+5)这类隐式乘法结构,且天然排除孤立单个数字(要求表达式必须包含至少1个运算符/括号结构)。
2. 匹配后合法性校验
正则仅做结构初筛,复杂规则通过后置校验实现,灵活度和性能更高:
// 输入字符串已提前移除所有空格 const result = message.match(exprReg) || []; const validResults = result.filter(expr => { // 排除含变量、等式的内容 if (/[a-zA-Z=]/.test(expr)) return false; // 排除连续运算符 if (/[+\-*/^]{2,}/.test(expr)) return false; // 排除单个数字带多个小数点的非法结构 if (/\d*\.\d*\./.test(expr)) return false; // 排除仅零散括号组合 if (/^\(*\)*$/.test(expr)) return false; // 排除除以0的无效表达式 if (expr.includes("/0")) return false; // 括号平衡性校验,不需要校验未闭合括号可注释该行 // if (!areBracketsBalanced(expr) && /[()]/.test(expr)) return false; return true; });
3. 扩展stringMath兼容能力
针对stringMath不支持隐式乘法、^运算符的问题,计算前做字符预处理即可:
validResults.forEach(expr => { // 补全隐式乘号:34(5+5) → 34*(5+5) let processedExpr = expr.replace(/(\d|\))\(/g, '$1*('); // 转换^为stringMath支持的指数格式,若依赖包支持**则替换为**,不支持可自行替换为对应指数语法 processedExpr = processedExpr.replace(/\^/g, '**'); // 执行计算 console.log(stringMath(processedExpr)); });
内容的提问来源于stack exchange,提问作者krrrrrrrrrrrr
相关产品推荐
相关产品推荐

