2017-02-09 13 views
1

У меня есть этот простой калькулятор калькулятора, но он не позволяет власти ^.Как получить вход 2^3 в Math.pow (2, 3)?

function getValues() { 
 
    var input = document.getElementById('value').value; 
 

 
    document.getElementById('result').innerHTML = eval(input); 
 

 
}
<label for="value">Enter: </label><input id="value"> 
 

 
    <div id="result">Results</div> 
 

 
    <button onclick="getValues()">Get Results</button>

Я попытался с помощью input = input.replace('^', 'Math.pow(,)');

Но я не знаю, как получить значения перед '^' и после того, как в скобках.

Пример: (1 + 2)^3^3 следует дать 7,625,597,484,987

+5

Простой случай, когда это просто 'х^y' где' х, y' целые числа является довольно выполнимо с помощью простого регулярного выражения , Однако правильное разбирательство чего-то типа '(2 + 34)^5', очевидно, более сложное. Не могли бы вы уточнить, что вы хотите сделать? – CollinD

+0

см.: [Основы для выражения оценки выражения] (http://stackoverflow.com/a/20919547/2521214) – Spektre

ответ

2

Используйте регулярное выражение с группами захвата:

input = '3 + 2 ^3'; 
 
input = input.replace(/(\d+)\s*\^\s*(\d+)/g, 'Math.pow($1, $2)'); 
 
console.log(input);

Это будет работать только тогда, когда аргументы просто цифры. Он не будет работать с суб-выражений или когда вы повторить его, как

(1+2)^3^3 

Это потребует написания рекурсивного спуска парсер, и это гораздо больше работы, чем я готов поставить в ответ здесь. Получите учебник по дизайну компилятора, чтобы узнать, как это сделать.

+1

Это идеальное решение, поскольку оно позволяет выражениям с несколькими операциями – AmericanUmlaut

0

Получить свой вклад в строку и сделать ...

var input = document.getElementById('value').value; 
var values = input.split('^'); //will save an array with [value1, value 2] 
var result = Math.pow(values[0], values[1]); 
console.log(result); 

Это только если только операция является '^'

EDIT: Saw пример после редактирования, это больше не работает.

0
function getValues() { 
    var input = document.getElementById('value').value; 

    // code to make^work like Math.pow 
    input = input.replace('^', '**'); 

    document.getElementById('result').innerHTML = eval(input); 

} 

Оператор ** может заменить Math.pow функции в большинстве современных браузеров. Следующая версия Safari (v10.1), выходящая в любой день, поддерживает ее.

1

Я не думаю, что вы сможете сделать это с простой заменой.

Если вы хотите разобрать операторы infix, вы создадите два стека, один для символов, другой для чисел. Затем последовательно следуйте формуле, игнорируя все остальное, кроме символов, чисел и закрывающей круглой скобки. Поместите символы и цифры в свои стеки, но когда вы столкнетесь с закрывающим париком, возьмите последний символ и примените его к двум последним цифрам. (Был изобретен Дейкстры, я думаю)

const formula = '(1+2)^3^3' 
 

 

 
const symbols = [] 
 
const numbers = [] 
 

 
function apply(n2, n1, s) { 
 
    if (s === '^') { 
 
    return Math.pow(parseInt(n1, 10), parseInt(n2, 10)) 
 
    } 
 
    
 
    return eval(`${n1} ${s} ${n2}`) 
 
} 
 

 
const applyLast =() => apply(numbers.pop(), numbers.pop(), symbols.pop()) 
 

 
const tokenize = formula => formula.split(/(\d+)|([\^\/\)\(+\-\*])/).filter(t => t !== undefined && t !== '') 
 

 
const solver = (formula) => { 
 
    const tf = tokenize(formula) 
 

 
    for (let l of formula) { 
 
    const parsedL = parseInt(l, 10) 
 
    if (isNaN(parsedL)) { 
 
     if (l === ')') { 
 
     numbers.push(applyLast()) 
 
     continue 
 
     } else { 
 
     if (~['+', '-', '*', '/', '^'].indexOf(l)) 
 
      symbols.push(l) 
 
     continue 
 
     } 
 
     
 
    } 
 
    numbers.push(l) 
 
    } 
 
    
 
    while (symbols.length > 0) 
 
    numbers.push(applyLast()) 
 
    
 
    return numbers.pop() 
 
} 
 

 
console.log(solver(formula))

+0

это действительно крутой подход – fafl

0

Как сказано в других ответах здесь, вам нужен реальный анализатор правильно решить эту проблему. Регулярное выражение будет решать простые случаи, но для вложенных операторов вам нужен рекурсивный синтаксический анализатор. Для Javascript одна библиотека, которая предлагает это, - peg.js.

В вашем случае пример, приведенный в online version может быть быстро расширен для обработки полномочий:

Expression 
    = head:Term tail:(_ ("+"/"-") _ Term)* { 
     var result = head, i; 

     for (i = 0; i < tail.length; i++) { 
     if (tail[i][1] === "+") { result += tail[i][3]; } 
     if (tail[i][1] === "-") { result -= tail[i][3]; } 
     } 

     return result; 
    } 

Term 
    = head:Pow tail:(_ ("*"/"/") _ Pow)* { // Here I replaced Factor with Pow 
     var result = head, i; 

     for (i = 0; i < tail.length; i++) { 
     if (tail[i][1] === "*") { result *= tail[i][3]; } 
     if (tail[i][1] === "/") { result /= tail[i][3]; } 
     } 

     return result; 
    } 

// This is the new part I added 
Pow 
    = head:Factor tail:(_ "^" _ Factor)* { 
     var result = 1; 
     for (var i = tail.length - 1; 0 <= i; i--) { 
      result = Math.pow(tail[i][3], result); 
     } 
     return Math.pow(head, result); 
    } 

Factor 
    = "(" _ expr:Expression _ ")" { return expr; } 
/Integer 

Integer "integer" 
    = [0-9]+ { return parseInt(text(), 10); } 

_ "whitespace" 
    = [ \t\n\r]* 

возвращает ожидаемый результат 7625597484987 для входной строки (1+2)^3^3.