简体   繁体   English

在以下情况下,if-else树是最好的方法吗?

[英]Is an if-else tree the best way to go in the following case?

What I'm doing: 我在做什么:

I'm creating a simple calculator in Java, that reads a string that has been written using postfix notation (for example: 3 4 +). 我正在用Java创建一个简单的计算器,它读取一个使用后缀表示法编写的字符串(例如:3 4 +)。 It then takes the string and starts reading it from left to right. 然后它接受字符串并从左到右开始读取它。 It stores each number it finds and then applies the following operator. 它存储它找到的每个数字,然后应用以下运算符。 For example: 3 4 + --> store 3, store 4, run 3 + 4 and store result. 例如:3 4 + - >存储3,存储4,运行3 + 4并存储结果。

What I need help with: 我需要帮助的是:

In what way characters should be checked against pre-defined operators (if(c == '/') etc). 应该以什么方式检查字符与预定义的运算符(if(c =='/')等)。 What alternatives are there in my case to an if-else tree, and which one should I choose if I want to be able to add new operators with minimum effort (and minimum toll on performance). 在我的情况下,对于if-else树有哪些替代方案,如果我希望能够以最小的努力添加新的运算符(以及最低的性能损失),我应该选择哪一个。 What is generally considered good practice? 什么通常被认为是良好的做法?

If this is a calculator for humans to use, stop thinking about performance (as in execution speed). 如果这是一个供人类使用的计算器,请停止考虑性能(如执行速度)。 No human will ever come close to noticing the difference between an if-tree and any other implementation. 没有人能够注意到if-tree和任何其他实现之间的区别。

That said, you might want to try implementing some kind of Operator class, that knows how to apply itself to arguments, and then use a hash from the operator name (strings like "+", "-", "*" and so on) to an appropriate instance. 也就是说,您可能希望尝试实现某种类型的Operator类,它知道如何将自身应用于参数,然后使用运算符名称中的哈希值(字符串如“+”,“ - ”,“*”等等) )到适当的实例。

I wouldn't worry about performance as the computer can parse/calculate the data 1 million times faster than you can type the formula (and that is not an exaguration) 我不担心性能,因为计算机可以解析/计算数据的速度比键入公式快100万倍(这不是夸大)

The way I would approach it is to use if/else or use a switch statement 我接近它的方法是使用if / else或使用switch语句

switch(ch) {
  case '+':

     break;
  case '-':

     break;
  // etc.
}

If you encapsulate your operations as objects, you can often use a data structure to replace a switch -like statement and hopefully will simply adding operations in the future. 如果将操作封装为对象,则通常可以使用数据结构替换类似switch的语句,并希望将来只添加操作。

For example, this is one approach for encapsulating operations as objects: using an Enum to represent the operations: 例如,这是将操作封装为对象的一种方法:使用Enum来表示操作:

http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html

public enum Operation {
  PLUS   { double eval(double x, double y) { return x + y; } },
  MINUS  { double eval(double x, double y) { return x - y; } },
  TIMES  { double eval(double x, double y) { return x * y; } },
  DIVIDE { double eval(double x, double y) { return x / y; } };

  // Do arithmetic op represented by this constant
  abstract double eval(double x, double y);
}

You could extend this example to associate a symbol with each operation and provide a static method to look up the operation associated with symbol. 您可以扩展此示例以将符号与每个操作相关联,并提供静态方法以查找与符号关联的操作。 [[ I'm torn about this mixing UI/view code with the logic/domain code, but you mentioned you want simple, so perhaps this is okay for your program.]] [[我对这个混合的UI /视图代码与逻辑/域代码撕裂,但你提到你想要简单,所以也许这对你的程序是好的。]]

If you encapsulate your operations as objects, then you can consider a data structure to replace switch-like code: 如果将操作封装为对象,则可以考虑使用数据结构来替换类似交换的代码:

  • if there will be a lot of operations, consider building a hashmap to map symbols to operations. 如果会有很多操作,请考虑构建一个hashmap以将符号映射到操作。

  • if there are a small number of operations, it may be cheap enough to have a collection of all operations and simply iterate through all operations to ask each if they act on the user-provided symbol and use the first found. 如果存在少量操作,则可能足够便宜以具有所有操作的集合并且简单地遍历所有操作以询问每个操作是否它们对用户提供的符号起作用并使用第一个找到的操作。

你正在寻找的是由一个地图实现的命令模式 ,其中Character对象作为键,实例将处理接口实现为值。

I would do it by creating an Operator superclass, which is extended by single operations, follows an example (forgive me for errors, I'm not trying this). 我会通过创建一个由单个操作扩展的Operator超类来做到这一点,遵循一个例子(原谅我的错误,我不是在尝试这个)。

abstract class Operator {
    String simbol;
    abstract Double calculate(Double firstOperand, Double secondOperand)
}

class Sum extends Operator {
    simbol = "+";
    Double calculate(Double firstOperand, Double secondOperand){
        return firstOperand + secondOperand;
    }    
}

class OperatorRecognizer {
    List<Operator> operators;
    public Operator recognize(String readOperator){
        for(Operator operator : operators){
            if(operator.getSymbol().equals(readOperator)){
                return operator;
            }
        }
    }
}

While reading a line I would do it this way: 在阅读一行时我会这样做:

OperatorFactory.recognize(readOperator).calculate(firstOperand, secondOperand);

This way when you have to add a single operation you just add one class. 这样,当您必须添加单个操作时,您只需添加一个类。

EDIT: lol ok, it seems others have said this same thing, I'll leave this here anyway ^^" 编辑:大声笑好吧,似乎其他人说过同样的事情,我会留在这里无论如何^^“

Interesting question. 有趣的问题。 Like many people here, micro optimization causes more evil than good. 像这里的许多人一样,微观优化导致更多的邪恶而不是善。 But without throwing any design patten at you or idea for optimization, this is what I would do. 但是,如果没有任何设计模式或优化的想法,这就是我要做的。

I will create am Enum for all operations. 我将为所有操作创建枚举。 I will also create a member function in this enum that takes a var args parameter and a operation enum and iteratively apply the enum operation on the arguements. 我还将在此枚举中创建一个成员函数,该函数接受var args参数和操作枚举,并在参数上迭代地应用枚举操作。

I will also create an String utility class (for input processing), that Iterates thro all the operation enum values and performs a regular expression check on input string to identify the operation specified by a given string ( regex because I want to make sure of Postfix notation). 我还将创建一个String实用程序类(用于输入处理),它迭代所有操作枚举值并对输入字符串执行正则表达式检查以标识给定字符串指定的操作(正则表达式因为我想确保Postfix符号)。 Once it identifies the operation, then it delegates to the enum's member function to perform the operation. 一旦识别出操作,它就会委托enum的成员函数来执行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM