本例需求:需要在代碼中動(dòng)態(tài)計(jì)算數(shù)學(xué)公式(含變量),代碼中通過(guò)字符串變量替換生成一個(gè)數(shù)學(xué)可執(zhí)行公式科汗,然后通過(guò)調(diào)用eval(str)函數(shù)計(jì)算出結(jié)果程奠,由于公式存在除數(shù)變量為0的情況,需要對(duì)該段表達(dá)式進(jìn)行乘0處理车柠,例如:公式 = a / (b-2)瓷患,當(dāng)a=10, b=2時(shí)骡尽,代入eval('10/(2-2)'),存在除數(shù)為0擅编,所以我的處理是通過(guò)獲取除數(shù)表達(dá)式(b-2)優(yōu)先計(jì)算攀细,當(dāng)計(jì)算為0時(shí),代入eval('10*0')爱态,相當(dāng)于把公式替換成:a * 0谭贪,需要用到方法如下:
1、校驗(yàn)數(shù)學(xué)公式方法
/**
* 校驗(yàn)數(shù)學(xué)公式是否正確
* @param 公式字符串
* @returns true: 正確锦担、false-錯(cuò)誤
*/
function checkFormula(str) {
try {
var tmp = str.replace(/[a-zA-Z]+[0-9]*/g, 10);
eval(tmp);
return true;
} catch(err) {
return false;
}
}
2俭识、遞歸獲取所有除數(shù)
/**
* 獲取數(shù)學(xué)公式中的所有除數(shù),如果有存在/(..)/..情況洞渔,也算一個(gè)組合除數(shù)
* @param str 數(shù)學(xué)公式字符串
* @param pattern 正則表達(dá)式
* @param divisorArr 返回的所有除數(shù)數(shù)組
*/
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); //排除第一個(gè)/符號(hào)
divisorArr.push(s); //添加到數(shù)組中套媚,可能存在異常公式,后面會(huì)進(jìn)行統(tǒng)一校驗(yàn)處理
//如果除數(shù)是被()包含的運(yùn)算磁椒,存在/(..)/..情況堤瘤,則獲取單個(gè)有效除數(shù),采用堆棧形式
if(s.indexOf("(") == 0){
var stock = []; //當(dāng)stock.length == 0時(shí)衷快,說(shuō)明( == )數(shù)量
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){ //找到除數(shù)
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宙橱、測(cè)試
//測(cè)試
function main() {
// var divisorArr1 = []; //緩存不含括號(hào)的除數(shù)
var divisorArr2 = []; //緩存所有情況的除數(shù)
var divisorArr3 = []; //最后返回的除數(shù)結(jié)果
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]*"; //獲取含括號(hào)的除數(shù)正則表達(dá)式
// var pattern1= "\\/\\([a-zA-Z0-9\\+\\-\\*\\/]+\\)|\\/[a-zA-z]+[0-9]*"; //獲取不含括號(hào)的除數(shù)正則表達(dá)式
//數(shù)學(xué)公式校驗(yàn)成功則進(jìn)行除數(shù)獲取
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);
}
});
}
//排序姨俩,按照字符長(zhǎng)度從小到大
divisorArr3.sort(function (a, b) {
return a.length - b.length;
});
console.log(divisorArr3.join(","));
}else {
console.log("公式語(yǔ)法錯(cuò)誤蘸拔,請(qǐng)檢查师郑!");
return;
}
}
注意:代碼僅測(cè)試了一些公式表達(dá)式,如果存在問(wèn)題调窍,歡迎大家指正1γ帷!邓萨!