JavaScript-写一个可以解析数学表达式的函数(无eval) [英] JavaScript -- write a function that can solve a math expression (without eval)

查看:87
本文介绍了JavaScript-写一个可以解析数学表达式的函数(无eval)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最终我要接受这个:

2x + 3 = 5

求解x,方法是先从两边减去3,然后再2x = 2,然后将两边除以2,从而得到x = 1.我在想很多事情,应该如何在JavaScript中创建这样的函数,该函数可以返回按顺序完成的一系列步骤,包括结果.显然,"eval"对此无能为力,因此貌似必须重新创建方程式.

and solve for x, by first subtract 3 from both sides so 2x = 2, then divide both sides by 2 so x = 1. I was thinking a lot how one should go about making a function like this in JavaScript that can return an array of the steps done in order, including the result. Obviously "eval" wouldn't do anything for this, so seemingly one has to re-create equations.

我最初想到首先忽略X,然后尝试制作一个可以解决简单方程式的函数,而无需eval或任何内置函数.

I initially thought to first of all, ignore X, and just try to make a function that can solve simple equations, without eval or any built-in function.

我认为第一步是使用.split分解术语,但是我遇到了一些麻烦,因为我需要拆分多个 个符号.例如,假设我有一个简单的表达式求值:3 - 6 * 3 / 9 + 5.因此,在我们甚至未按顺序进行操作之前,将每个术语分解(并将它们分类)是困难的部分,这是我目前主要的具体问题.

I figured that the first step is to break up the terms using .split, but I was having some trouble with this, as I need to split for multiple symbols. For example, say I have the simple expression to evaluate: 3 - 6 * 3 / 9 + 5. So before we even get into order of operations, just splitting up each term (and categorizing them) is the hard part, which is the main concrete-question I have at this point.

我开始只是一个接一个地拆分,但是我遇到了一些问题,尤其是考虑顺序.

I started simply splitting one after the other, but I was having some problems, and especially considering the order.

function solve(eq) {
    var minuses = eq.split("-"),
            pluses = minuses.map(x=> x.split("+")),
            timeses = pluses.map(x=>x.map(y=>y.split("*"))),
      dividers = timeses.map(x=>x.map(y=>y.map(z=>z.split("/"))));
            console.log(minuses, pluses, timeses, dividers);
}

solve("3 - 6 * 3 / 9 + 5");

如您所见,对于每个连续的运算符,我都需要遍历前一个运算符的每个元素以进行拆分,然后剩下一个数组数组等.

As you can see, for each successive operator I need to map through each of he elements of the previous one to split it, and then I am left with an array of arrays etc...

所以1)如何在不为每个变量创建新变量的情况下更有效地拆分这些术语,并手动递归地映射每个变量?似乎我应该只拥有某种数组的字典来跟踪操作顺序(现在不考虑括号或指数):["*","/","+","-"]-并给定该数组,生成类似于上面示例中的最后一个数组的内容(除法器" )仅包含常量,并以某种方式跟踪每个存储的数组遵循哪些元素...

So 1) how can I split up these terms more efficiently, without making a new variable for each one, and manually recursively mapping through each one? Seemingly I should just have some kind of dictionary of array keeping track of orders of operations (not considering parenthesis or exponents now): ["*","/","+","-"] -- and given that array, generate something similar to the last array in the above example ("dividers") which contains only constants, and somehow keep track of the which elements each of the stored arrays follows...

和2)在给定值数组的情况下如何求解表达式?

我只是对逻辑有些困惑,我想我需要从最后一个数组开始处理,一次求解一个常量,跟踪哪个运算符是当前的,但是我不确定完全是

I was just a little confused with the logic, I guess I need to work up from the last array and solve the constants one at a time, keeping track of which operator is the current one, but I'm not sure how exactly.

推荐答案

您可以按照以下步骤操作:

You can do that in following steps:

  • 首先使用split()并除以+-,这将在乘法和除法之后发生.
  • 然后在数组上使用map()并通过*/再次使用split().
  • 现在我们有一个函数,该函数将使用运算符将​​数字数组评估为单个数字.
  • 传递嵌套数组以完成乘法和除法.
  • 然后将结果再次传递给sovleSingle并执行加法和减法.
  • First of all use split() and split by the + and - which will occur after multiplication and division.
  • Then use map() on array and split() it again by * and /.
  • Now we have a function which will which will evaluate an array of numbers with operators to single number.
  • Pass the nested array to complete multiplication and division.
  • Then pass that result again to sovleSingle and perform addition and subtraction.

该功能与eval相同,只要没有方括号().

The function works same as eval as long as there are no brackets ().

注意:这与在+-中首先出现或在*/中首先出现无关紧要.但是*,/应该在+,-

Note: This doesnot matters the which occurs first among + and - or which occurs first among * and /. But *,/ should occur before +,-

function solveSingle(arr){
  arr = arr.slice();
  while(arr.length-1){
    if(arr[1] === '*') arr[0] = arr[0] * arr[2]
    if(arr[1] === '-') arr[0] = arr[0] - arr[2]
    if(arr[1] === '+') arr[0] = +arr[0] + (+arr[2])
    if(arr[1] === '/') arr[0] = arr[0] / arr[2]
    arr.splice(1,1);
    arr.splice(1,1);
  }
  return arr[0];
}

function solve(eq) {
  let res = eq.split(/(\+|-)/g).map(x => x.trim().split(/(\*|\/)/g).map(a => a.trim()));
  res = res.map(x => solveSingle(x)); //evaluating nested * and  / operations.
   
  return solveSingle(res) //at last evaluating + and -
  
  
}

console.log(solve("3 - 6 * 3 / 9 + 5")); //6
console.log(eval("3 - 6 * 3 / 9 + 5")) //6

这篇关于JavaScript-写一个可以解析数学表达式的函数(无eval)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆