带括号的简单计算器如何工作? [英] How does a simple calculator with parentheses work?

查看:24
本文介绍了带括号的简单计算器如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解计算器的工作原理.例如,假设我们有这样的中缀符号输入:

I want to learn how calculators work. For example, say we have inputs in infix notation like this:

1 + 2 x 10 - 2

1 + 2 x 10 - 2

解析器必须遵守数学中的通用规则.在上面的例子中,这意味着:

The parser would have to respect common rules in math. In the above example this means:

1 + (2 x 10) - 2 = 19(而不是 3 x 10 - 2 = 28)

1 + (2 x 10) - 2 = 19 (rather than 3 x 10 - 2 = 28)

然后考虑这个:

1 + 2 x ((2/9) + 7) - 2

1 + 2 x ((2 / 9) + 7) - 2

它是否涉及抽象语法树?二叉树?如何确保运算顺序在数学上是正确的?我必须使用调车码算法将其转换为后缀表示法吗?然后,我将如何用后缀表示法解析它?为什么首先要转换?

Does it involve an Abstract Syntax Tree? A binary tree? How is the order of operations ensured to be mathematically correct? Must I use the shunting-yard algorithm to convert this to postfix notation? And then, how would I parse it in postfix notation? Why convert in the first place?

是否有教程展示了这些相对简单的计算器是如何构建的?或者有人可以解释一下吗?

Is there a tutorial which shows how these relatively simple calculators are built? Or can someone explain?

推荐答案

对表达式求值的一种方法是使用递归下降解析器.http://en.wikipedia.org/wiki/Recursive_descent_parser

One way to do evaluate an expression is with a recursive descent parser. http://en.wikipedia.org/wiki/Recursive_descent_parser

这是一个 BNF 形式的语法示例:http://en.wikipedia.org/wiki/Backus-Naur_form

Here's an example grammar in BNF form: http://en.wikipedia.org/wiki/Backus-Naur_form

Expr ::= Term ('+' Term | '-' Term)*
Term ::= Factor ('*' Factor | '/' Factor)*

Factor ::= ['-'] (Number | '(' Expr ')')

Number ::= Digit+

这里*表示前面的元素重复0次或多次,+表示重复一次或多次,方括号表示可选.

Here * means the preceding element is repeated zero or more times, + means one or more repeats, square brackets means optional.

语法确保最高优先级的元素首先收集在一起,或者在这种情况下,首先评估.当您访问语法中的每个节点时,您不是构建抽象语法树,而是评估当前节点并返回值.

The grammar ensures that the elements of highest precedence are collected together first, or in this case, evaluated first. As you visit each node in the grammar, instead of building an abstract syntax tree, you evaluate the current node and return the value.

示例代码(不完美,但应该让您了解如何将 BNF 映射到代码):

Example code (not perfect but should give you an idea of how to map BNF to code):

def parse_expr():
  term = parse_term()
  while 1:
    if match('+'):
      term = term + parse_term()
    elif match('-'):
      term = term - parse_term()
    else: return term

def parse_term():
  factor = parse_factor()
  while 1:
    if match('*'):
      factor = factor * parse_factor()
    elif match('/'):
      factor = factor / parse_factor()
    else: return factor

def parse_factor():
  if match('-'):
    negate = -1
  else: negate = 1
  if peek_digit():
    return negate * parse_number()
  if match('('):
    expr = parse_expr()
    if not match(')'): error...
    return negate * expr
  error...

def parse_number():
  num = 0
  while peek_digit():
    num = num * 10 + read_digit()
  return num

要显示您的 1 + 2 * 10 - 2 示例将如何评估:

To show how your example of 1 + 2 * 10 - 2 would evaluate:

call parse_expr                              stream is 1 + 2 * 10 - 2
  call parse term
    call parse factor
      call parse number which returns 1      stream is now + 2 * 10 - 2
    match '+'                                stream is now 2 * 10 - 2
    call parse factor
      call parse number which returns 2      stream is now * 10 - 2
      match '*'                              stream is now 10 - 2
      call parse number which returns 10     stream is now - 2
      computes 2 * 10, return 20
    compute 1 + 20 -> 21
    match '-'                                stream is now 2
    call parse factor
      call parse number which returns 2      stream is empty
    compute 21 - 2, return 19
  return 19

这篇关于带括号的简单计算器如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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