js浮点运算式
結(jié)果
calc('0.23*-0.03+(4*0.2)') =>0.7931
代碼
//加|減|乘|除 浮點運算 const floatMulti = (a, b) => {let m = 0, s1 = a.toString(), s2 = b.toString(), s1l = s1.split('.')[1], s2l = s2.split('.')[1]m = (s1l ? s1l.length : 0) + (s2l ? s2l.length : 0)return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m) } const floatSub = (a, b) => {let m = 0, s1 = a.toString(), s2 = b.toString(), s1l = s1.split('.')[1], s2l = s2.split('.')[1]m = Math.max((s1l ? s1l.length : 0) ,(s2l ? s2l.length : 0))return(Number(s1)*Math.pow(10, m) - Number(s2)*Math.pow(10, m)) / Math.pow(10, m) } const floatAdd = (a, b) => {let m = 0, s1 = a.toString(), s2 = b.toString(), s1l = s1.split('.')[1], s2l = s2.split('.')[1]m = Math.max((s1l ? s1l.length : 0) ,(s2l ? s2l.length : 0))return (Number(s1)*Math.pow(10, m) + Number(s2)*Math.pow(10, m)) / Math.pow(10, m) } const floatDev = (a, b) => {let m = 0, s1 = a.toString(), s2 = b.toString(), s1l = s1.split('.')[1], s2l = s2.split('.')[1]m = (s1l ? s1l.length : 0) + (s2l ? s2l.length : 0)return (Number(s1.replace('.', '')) / Number(s2.replace('.', ''))) / Math.pow(10, m) } /* * 浮點運算式 * */ export const calc = (() => {//一般的算數(shù)表達式即為中綴表達式// let str = "1+((2 + 3 ) * 4 ) - 5 ";//運算符權(quán)重const sdw = { '+': 1, '-': 1, '*': 2, '/': 2 };//循環(huán)安全數(shù)let saveCircle = 137;/***判斷是 運算符|操作數(shù)|括號* 【-】字符前面有任何其他運算符則本身被當作數(shù)字一部分*@return 1:操作數(shù) 2:括號 0:運算符*/const typeChk = (d) => /^-*[\.\d]+$/.test(d) ? 1 : (/[\(\)]/.test(d) ? 2 : 0)/** 操作符操作方法* */const handle = { '+': floatAdd, '-': floatSub, '*': floatMulti, '/': floatDev }/*** 處理輸入* 1) 替換中英括號* 2) 去除空格* 3) 小數(shù)點前后非數(shù)字,則去除* 3) 小數(shù)點之前為空,后面為數(shù)字則默認前面添加0* 4) 返回字符分割*/const dealStr = (str) => str//替換左右括號.replace(/(/, '(').replace(/)/, ')')//替換空字符.replace(/[^\d\.\(\)\+\*\/-]/g, '')//替換-// .replace(/(\d)-/g,'$1+-')// .replace(/--/g,'+')// .replace(/-\(/g,'-1*(')// .replace(/-/g,'+-1*').match(/(((?<=[^\d])-[\.\d]+)+)|(^-[\.\d]+)|([\d\.]+)|([\(\)\+\*\/-])/g)//中綴表達式轉(zhuǎn)前綴表達式并計算return (str) => {let operand = [];//操作數(shù)棧let operator = [];//操作符棧//去空格(主要是避免數(shù)字被空格拆分),分割成數(shù)組let arr = dealStr(str);// log(arr)//按照規(guī)則入棧let type;for (let i = arr.length - 1, curr; (curr = arr[i]) != null; i--) {type = typeChk(curr);if (type === 1) {operand.push(+curr)} else if (type === 0) {let si = 0, stackTop;while (true && si++ < saveCircle) {stackTop = operator[operator.length - 1];if (stackTop == null || stackTop === ')') {operator.push(curr);break;} else if (sdw[curr] >= sdw[stackTop]) {operator.push(curr);break;} else {operand.push(operator.pop())}}} else {if (curr === ')') {operator.push(curr)}else{let s, si = 0;while (s !== ')' && si++ < saveCircle) {s = operator.pop();if (s === ')') breakoperand.push(s)}}}}//將操作符棧中剩下的彈出壓入操作數(shù)棧// operand = [...operand, ...operator.reverse()];// num => ["5", "4", "3", "2", "+", "×", "1", "+", "-"]//"1+((2 + 3 ) × 4 ) - 5 "let prevStack = [...operator, ...operand.reverse()];// ["-", "+", "1", "×", "+", "2", "3", "4", "5"]//計算let resultStack = [], left, right;for (let i = prevStack.length - 1, curr; (curr = prevStack[i]) != null; i--) {if (typeChk(curr)) {//是操作數(shù)resultStack.push(curr)} else {//是操作符left = resultStack.pop();right = resultStack.pop();// console.log(left,right,curr)resultStack.push(handle[curr](left, right))}}// log(prevStack);//log(resultStack);return resultStack.length != 1 ? '表達式有誤' : resultStack[0]} })()總結(jié)
- 上一篇: android camera 显示过程,
- 下一篇: 计算机网络项目——最小网元设计(阶段二)