Esta es una función de calculadora básica. Solo hace sumas, restas, multiplicaciones, divisiones y paréntesis.
Tengo un bucle infinito en la llamada recursiva en la sección while que verifica si la cadena tiene paréntesis o no. Si hubiera enviado una cadena con 2 o más paréntesis a la función, se ha quedado atascada en el bucle. No pude entender qué hice mal.
const operators = ['+', '-', '*', '/', '(', ')']; const numbers = []; let arr; const array = []; function Calculate(string) { string.split('').map(char => { if (!operators.includes(char)) { numbers.push(char); } else { arr = numbers.join(''); numbers.splice(0); array.push(arr, char); } }); arr = numbers.join(''); const str = array.filter(char => char !== '').concat(arr); while (str.includes('(')) { // Checking parentheses let indexOpen = str.findIndex(char => char === '('); let indexClose = indexOpen + 1; let count = 1; while (count !== 0) { if (str[indexClose] === '(') { count++; } else if (str[indexClose] === ')') { count--; } indexClose++; } if ( !operators.includes(str[indexOpen - 1]) // str[indexOpen - 1] !== '+' && // str[indexOpen - 1] !== '-' && // str[indexOpen - 1] !== '*' && // str[indexOpen - 1] !== '/' ) { str.splice(indexOpen, 0, '*'); indexOpen++; indexClose++; } const strPara = str .filter((_, i) => i < indexClose - 1 && i > indexOpen) .join(''); str.splice(indexOpen, indexClose - indexOpen, Calculate(strPara)); } let indexMul; // Multiplication and division let indexDiv; while (str.includes('*') || str.includes('/')) { indexMul = str.findIndex(char => char === '*') === -1 ? str.length : str.findIndex(char => char === '*'); indexDiv = str.findIndex(char => char === '/') === -1 ? str.length : str.findIndex(char => char === '/'); if (indexMul < indexDiv) { str.splice(indexMul - 1, 3, +str[indexMul - 1] * +str[indexMul + 1] + ''); } else if (indexDiv < indexMul) { str.splice( indexDiv - 1, 3, Math.trunc(+str[indexDiv - 1] / +str[indexDiv + 1]) + '' ); } } while (str.length !== 1) { // Addition and subtraction if (str[1] === '+') { str.splice(0, 3, +str[0] + +str[2] + ''); } if (str[1] === '-') { str.splice(0, 3, +str[0] - +str[2] + ''); } } return str; } console.log(Calculate('3(16-(10-4)+2)/2(4*2)+1'));
Hice esto.
Tenga cuidado, este código hace los cálculos uno tras otro sin administrar la precedencia de los operadores.
La forma recursiva:
let strCalc = '3(16-(10-4)+2)/2(4*2)+1' document.write(`${ strCalc } = ${ Calculate(strCalc) }`) document.write(`<br><br>`) strCalc = '5 ( -18.4 + 2 ) / ( -2 ( 4 * -.5 )) + 1' document.write(`${ strCalc } = ${ Calculate(strCalc) }`) function Calculate(str) { const ops = str .match(/[\(\)\+\-\*\/]|((\d+\.?\d*)|(\.\d+))/g) .reduce((r,v)=> { if (isNaN(v)) { if (!r.opPrev || v==='(') { r.res.push(v) r.opPrev = ( v!==')' ) } else if (v==='-') // check negatives values r.sign='-'; } else { r.res.push(Number(`${r.sign}${v}`)) r.sign = '' r.opPrev = false } return r }, { res:[], opPrev:true, sign:'' }).res ; let Pos = 0 ; return makeCalc() ; function makeCalc() { let result = 0 , operand = '+' , val ; while ( Pos < ops.length && ops[Pos] !== ')' ) { val = ops[Pos] ; if ( val === '(' ) { operand ??= '*' // nullish assignement operator Pos++ val = makeCalc() // recurvive call } if ( isNaN(val) ) operand = val ; else { switch (operand) { case '+' : result += val; break; case '-' : result -= val; break; case '/' : result /= val; break; // may do 0 divide! case '*' : result *= val; break; } operand = null } Pos++ } return result } }