开发者

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

开发者 https://www.devze.com 2023-02-07 12:53 出处:网络
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 +). It then takes the string and starts reading it from

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 +). It then takes the string and starts reading it from left to right. It stores each number it finds and then applies the following operat开发者_如何学运维or. For example: 3 4 + --> store 3, store 4, run 3 + 4 and store result.

What I need help with:

In what way characters should be checked against pre-defined operators (if(c == '/') etc). 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). 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.

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.


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.

For example, this is one approach for encapsulating operations as objects: using an Enum to represent the operations:

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.]]

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.

  • 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.


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)

The way I would approach it is to use if/else or use a switch statement

switch(ch) {
  case '+':

     break;
  case '-':

     break;
  // etc.
}


What you are looking for is the Command Pattern implemented by a map with Character objects as key and instances implementing a handling interface as values.


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).

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.

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). Once it identifies the operation, then it delegates to the enum's member function to perform the operation.

0

精彩评论

暂无评论...
验证码 换一张
取 消