JS校验数学公式并获取所有除数字符串数组

本例需求:需要在代码中动态计算数学公式(含变量),代码中通过字符串变量替换生成一个数学可执行公式,然后通过调用eval(str)函数计算出结果,由于公式存在除数变量为0的情况,需要对该段表达式进行乘0处理,例如:公式 = a / (b-2),当a=10, b=2时,代入eval('10/(2-2)'),存在除数为0,所以我的处理是通过获取除数表达式(b-2)优先计算,当计算为0时,代入eval('10*0'),相当于把公式替换成:a * 0,需要用到方法如下:

1、校验数学公式方法

/**
 * 校验数学公式是否正确
 * @param 公式字符串
 * @returns true: 正确、false-错误
 */
function checkFormula(str) {
    try {
        var tmp = str.replace(/[a-zA-Z]+[0-9]*/g, 10);
        eval(tmp);
        return true;
    } catch(err) {
        return false;
    }
}

2、递归获取所有除数

/**
 * 获取数学公式中的所有除数,如果有存在/(..)/..情况,也算一个组合除数
 * @param str 数学公式字符串
 * @param pattern 正则表达式
 * @param divisorArr 返回的所有除数数组
 */
function listDivisor(str, pattern, divisorArr) {
    var arr = str.match(new RegExp(pattern, 'g'));
    if(arr && arr.length > 0){
        $.each(arr, function (i, s) {
            s = s.substring(1); //排除第一个/符号
            divisorArr.push(s); //添加到数组中,可能存在异常公式,后面会进行统一校验处理
            //如果除数是被()包含的运算,存在/(..)/..情况,则获取单个有效除数,采用堆栈形式
            if(s.indexOf("(") == 0){
                var stock = []; //当stock.length == 0时,说明( == )数量
                var tmp1 = "";
                var tmp2 = "";
                for(var j = 0; i < s.length; j++){
                    if("(" == s[j]){
                        stock.push(s[j]);
                    }
                    if(")" == s[j]){
                        stock.pop();
                    }
                    if(stock.length == 0){ //找到除数
                        tmp1 = s.substring(0, j+1);
                        break;
                    }
                }
                divisorArr.push(tmp1);
                if(tmp1.length < s.length){
                    tmp2 = s.substring(tmp1.length, s.length);
                }
                if(tmp1 && tmp1.indexOf("/") != -1){
                    listDivisor(tmp1, pattern, divisorArr);
                }
                if(tmp2 && tmp2.indexOf("/") != -1){
                    listDivisor(tmp2, pattern, divisorArr);
                }
            }
        });
    }
}

3、测试

//测试
function main() {
    // var divisorArr1 = []; //缓存不含括号的除数
    var divisorArr2 = []; //缓存所有情况的除数
    var divisorArr3 = []; //最后返回的除数结果
    var formula = "60+a/b+a/((240+c/d*2-1)+(a-a/(c-2+c/(f-2))))/(y-1/(z-1))";
    var pattern = "\\/\\(.+\\)|\\/[a-zA-z]+[0-9]*"; //获取含括号的除数正则表达式
    // var pattern1= "\\/\\([a-zA-Z0-9\\+\\-\\*\\/]+\\)|\\/[a-zA-z]+[0-9]*"; //获取不含括号的除数正则表达式
    //数学公式校验成功则进行除数获取
    if(formula && checkFormula(formula)){
        listDivisor(formula, pattern, divisorArr2); //递归获取
        if(divisorArr2 && divisorArr2.length > 0){
            $.each(divisorArr2, function (j, s2) {
                if(!divisorArr3.contains(s2) && checkFormula(s2)){
                    divisorArr3.push(s2);
                }
            });
        }
        //排序,按照字符长度从小到大
        divisorArr3.sort(function (a, b) {
            return a.length - b.length;
        });
        console.log(divisorArr3.join(","));
    }else {
        console.log("公式语法错误,请检查!");
        return;
    }
}

注意:代码仅测试了一些公式表达式,如果存在问题,欢迎大家指正!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 8,729评论 0 2
  • 第一章 前端三大语言:HTML(专门编写网页内容)、CSS(编写网页样式)、JS(专门编写网页交互行为) 能简写尽...
    fastwe阅读 4,721评论 0 0
  • 选择题部分 1.(),只有在发生短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。...
    skystarwuwei阅读 14,659评论 0 7
  • 1. 关于诊断X线机准直器的作用,错误的是()。 (6.0 分) A. 显示照射野 B. 显示中心线 C. 屏蔽多...
    我们村我最帅阅读 13,706评论 0 5
  • 所有小学数学知识点都在这里了,不分版本!替孩子收好 法则知识归类 (1)笔算两位数加法,要记三条 1、相同数位对齐...
    小淘气学习乐园阅读 4,813评论 0 4