国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

javascript中解析四則運算表達式的算法和示例

2019-11-20 14:17:03
字體:
來源:轉載
供稿:網友

在編寫代碼時我們有時候會碰到需要自己解析四則運算表達式的情況,本文簡單的介紹使用JavaScript實現對簡單四則運算表達式的解析。

一、熟悉概念

中綴表示法(或中綴記法)是一個通用的算術或邏輯公式表示方法, 操作符是以中綴形式處于操作數的中間(例:3 + 4)。也就是我們最常用的算術表達式,中綴表達式對于人類來說比較容易理解,但是不易于計算機解析。

逆波蘭表示法(Reverse Polish notation,RPN,或逆波蘭記法),是一種是由波蘭數學家揚?武卡謝維奇1920年引入的數學表達式方式,在逆波蘭記法中,所有操作符置于操作數的后面,因此也被稱為后綴表示法。逆波蘭記法不需要括號來標識操作符的優先級。逆波蘭表示法容易使用堆棧結構對表達式進行解析并計算,所以,這里我們解析四則元素表達式,是先從中綴表達式,轉換為逆波蘭表達式。然后再計算值。

二、轉換流程

中綴表達式轉換為后綴表達式(調度場算法)

1.輸入隊列彈出一個記號
2.如果記號為數字,添加到輸出隊列中
3.如果是一個操作符(+-*/)則比較它與輸出堆棧中棧頂的操作符,如果優先級小于或等于棧頂的操作符,那么將棧頂的操作符彈出并加入輸出隊列(循環,直到上述條件不滿足),最后將本次的操作符壓入堆棧。
4.如果是一個左括號,壓入堆棧
5.如果是一個右括號,從棧中不斷的彈出操作符,并加入輸出隊列,知道棧頂的元素為左括號。彈出左括號,不加入輸出隊列。如果沒有發現左括號,說明原來的表達式中括號不對稱,有錯誤。
6.如果輸入隊列為空,而棧中尚有操作符時,如果棧頂的操作符為左括號,則說明原表達式有不匹配的括號。將棧中的操作符逐個彈出,加入輸出隊列。
7.完成

三、轉換代碼實現

function isOperator(value){	var operatorString = "+-*/()";	return operatorString.indexOf(value) > -1}function getPrioraty(value){	switch(value){		case '+':		case '-':			return 1;		case '*':		case '/':			return 2;		default:			return 0;	}}function prioraty(o1, o2){	return getPrioraty(o1) <= getPrioraty(o2);}function dal2Rpn(exp){	var inputStack = [];	var outputStack = [];	var outputQueue = [];	for(var i = 0, len = exp.length; i < len; i++){		var cur = exp[i];		if(cur != ' ' ){			inputStack.push(cur);		}	}	console.log('step one');	while(inputStack.length > 0){		var cur = inputStack.shift();		if(isOperator(cur)){			if(cur == '('){				outputStack.push(cur);			}else if(cur == ')'){				var po = outputStack.pop();				while(po != '(' && outputStack.length > 0){					outputQueue.push(po);					po = outputStack.pop();				}				if(po != '('){					throw "error: unmatched ()";				}			}else{				while(prioraty(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0){					outputQueue.push(outputStack.pop());				}				outputStack.push(cur);			}		}else{			outputQueue.push(new Number(cur));		}	}	console.log('step two');	if(outputStack.length > 0){		if(outputStack[outputStack.length - 1] == ')' || outputStack[outputStack.length - 1] == '('){			throw "error: unmatched ()";		}		while(outputStack.length > 0){			outputQueue.push(outputStack.pop());		}	}	console.log('step three');	return outputQueue;}console.log(dal2Rpn('1 + 2'));console.log(dal2Rpn('1 + 2 + 3'));console.log(dal2Rpn('1 + 2 * 3'));console.log(dal2Rpn('1 + 2 * 3 - 4 / 5'));console.log(dal2Rpn('( 1 + 2 )'));console.log(dal2Rpn('( 1 + 2 ) * ( 3 - 4 ) / 5'));console.log(dal2Rpn('( 1 + 2 ) * (( 3 - 4 ) / 5)'));

四、逆波蘭表達式求值

1.從輸入隊列中彈出一個記號
2.如果是操作數,加入輸出堆棧
3.如果是一個操作符,從輸出堆棧中彈出兩個操作數并進行計算,并將計算得到的值壓入輸出堆棧。
4.循環操作,如果輸入隊列為空,且輸出堆棧只有一個數則這個數為結果,否則是出現了多余的操作數。

五、計算代碼

function evalRpn(rpnQueue){	var outputStack = [];	while(rpnQueue.length > 0){		var cur = rpnQueue.shift();		if(!isOperator(cur)){			outputStack.push(cur);		}else{			if(outputStack.length < 2){				throw "unvalid stack length";			}			var sec = outputStack.pop();			var fir = outputStack.pop();			outputStack.push(getResult(fir, sec, cur));		}	}	if(outputStack.length != 1){		throw "unvalid expression";	}else{		return outputStack[0];	}}

六、結語

逆波蘭表示法,在初次接觸的時候感覺不太習慣,但是熟悉之后,會發現,其實思路特別簡單,不像中綴表示法,還有各種優先級啊,還有小括號之類的,邏輯特別麻煩,還是逆波蘭表示法比較簡潔,完全不用考慮優先級,也沒用小括號,中括號還有大括號攪局。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泽普县| 云霄县| 英吉沙县| 内乡县| 华池县| 泗水县| 河源市| 安福县| 缙云县| 玉门市| 峡江县| 正安县| 山西省| 伊川县| 申扎县| 黄骅市| 呼玛县| 虎林市| 柳河县| 阿拉善盟| 铜山县| 安岳县| 宁安市| 厦门市| 霍林郭勒市| 泰宁县| 贡觉县| 莫力| 黄山市| 江孜县| 瑞丽市| 天镇县| 大冶市| 化州市| 蒲城县| 禹城市| 义马市| 吴桥县| 章丘市| 玛纳斯县| 梁山县|