【问题标题】:Shorter solution to if,else if,else ifif,else if,else if 的较短解决方案
【发布时间】:2013-05-18 05:34:12
【问题描述】:

我正在寻找一种方法来缩短此代码并避免重复代码和 if 语句。我正在做的是创建一个计算器,用于搜索运算符“* / + -”的字符串并相应地执行它们。有什么想法吗?

if (exp.charAt(i) == '*') {
    newResult = Integer.parseInt(exp.substring(0, i)) * Integer.parseInt(exp.substring(i + 1, exp.length()));
    primeResult = newResult;
    System.out.println(primeResult);
} else if (exp.charAt(i) == '/') {
    newResult = Integer.parseInt(exp.substring(0, i)) / Integer.parseInt(exp.substring(i + 1, exp.length()));
    primeResult = newResult;
    System.out.println(primeResult);
} else if (exp.charAt(i) == '+') {
    newResult = Integer.parseInt(exp.substring(0, i)) + Integer.parseInt(exp.substring(i + 1, exp.length()));
    primeResult = newResult;
    System.out.println(primeResult);
} else if (exp.charAt(i) == '-') {
    newResult = Integer.parseInt(exp.substring(0, i)) - Integer.parseInt(exp.substring(i + 1, exp.length()));
    primeResult = newResult;
    System.out.println(primeResult);
}

另外,有没有一个解决方案可以接受超过 2 个操作数的字符串?即 5 + 10 * 2 / 3

【问题讨论】:

  • 使用switch()可能会减少你的代码
  • 对于多个操作数,分解复合语句,以正确的数学顺序 (PEMDAS) 执行每个操作。取结果并将其用作下一条语句的左操作数或右操作数。简单的。逐步分解和评估。
  • 对于多个操作数,您可以编写shunting yard algorithm。如果你愿意,我可以在我的答案中添加一个解释。

标签: java parsing math if-statement int


【解决方案1】:

您可以使用execute 方法编写AbstractCalculationOperation 类,并使用AddSubtract 等对其进行扩展。

然后,只需解析 leftHandrightHandcalculationOperation 并运行 calculationOperation.execute( rightHand, leftHand )

public interface CalculationOperation {
    double calculate ( double lh, double rh );
    long calculate ( long lh, long rh );
}

public class Add implements CalculationOperation {
    public static final CalculationOperation INSTANCE = new Add();
    public double calculate ( double rh, double lh ) { return lh + rh; }
    public long calculate ( long rh, long lh ) { return lh + rh; }
}

然后:

int lh = exp.substring(0, i);
int rh = exp.substring(i+1);
CalculationOperation op;
switch( exp.charAt(i) ) {
    case '*': op = Multiply.INSTANCE; break;
    case '/': op = Divide.INSTANCE; break;
    case '+': op = Add.INSTANCE; break;
    case '-': op = Subtract.INSTANCE; break;
}
newResult = op.calculate( rh, lh );
primeResult = newResult;
System.out.println(primeResult);

替代枚举变体:

public enum Calculation {
    ADD('+') {
        public int calculate( int lhs, int rhs ) { return lhs + rhs; }
        public long calculate( long lhs, long rhs ) { return lhs + rhs; }
        public float calculate( float lhs, float rhs ) { return lhs + rhs; }
        public double calculate( double lhs, double rhs ) { return lhs + rhs; }
    },
    SUBTRACT('-') {
        public int calculate( int lhs, int rhs ) { return lhs - rhs; }
        public long calculate( long lhs, long rhs ) { return lhs - rhs; }
        public float calculate( float lhs, float rhs ) { return lhs - rhs; }
        public double calculate( double lhs, double rhs ) { return lhs - rhs; }
    },
    MULTIPLY('*') {
        public int calculate( int lhs, int rhs ) { return lhs * rhs; }
        public long calculate( long lhs, long rhs ) { return lhs * rhs; }
        public float calculate( float lhs, float rhs ) { return lhs * rhs; }
        public double calculate( double lhs, double rhs ) { return lhs * rhs; }
    },
    DIVIDE('/') {
        public int calculate( int lhs, int rhs ) { return lhs / rhs; }
        public long calculate( long lhs, long rhs ) { return lhs / rhs; }
        public float calculate( float lhs, float rhs ) { return lhs / rhs; }
        public double calculate( double lhs, double rhs ) { return lhs / rhs; }
    };

    private final char textValue;
    Calculation ( char textValue )
    {
        this.textValue = textValue;
    }

    public abstract int calculate ( int lht, int rhs );
    public abstract long calculate ( long lht, long rhs );
    public abstract float calculate ( float lht, float rhs );
    public abstract double calculate ( double lht, double rhs );

    public static Calculation fromTextValue( char textValue ) {
        for( Calculation op : values() )
            if( op.textValue == textValue )
                return op;
        throw new IllegalArgumentException( "Unknown operation: " + textValue );
    }
}

然后:

int lh = exp.substring(0, i);
int rh = exp.substring(i+1);
Calculation op = Calculation.fromTextValue( exp.substring(i,1) );
newResult = op.calculate( lh, rh );
primeResult = newResult;
System.out.println(primeResult);

【讨论】:

  • 为了让它更干净,你可以把它变成一个enum Calculation,其中ADDSUBTRACT等都实现了计算方法和enum中的public static Calculation fromText(char textOp)方法处理switch
  • 枚举变体的优点是添加 LOGARITHMEXPONENT 只需向枚举添加一个条目(实现所有 4 种必需的方法 - int、float、long、double) .无需担心在任何地方更新 switch 语句,因为它只在一个地方使用。
【解决方案2】:

这是一个sn-p:

public static void main(String[] args) {

        float primeResult;
        String exp = "4-2";
        int i = 1;
        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("JavaScript");

        char[] myVar = new char[] { '*', '/', '-', '+' };

        for (int myVarCtr = 0; myVarCtr < myVar.length; myVarCtr++) {

            if (exp.charAt(i) == myVar[myVarCtr]) {

                try {
                    primeResult = Float.parseFloat(engine.eval(
                            (Integer.parseInt(exp.substring(0, i)))
                                    + Character.toString(myVar[myVarCtr])
                                    + (Integer.parseInt(exp.substring(i + 1,
                                            exp.length())))).toString());
                    System.out.println(primeResult);
                } catch (ScriptException e) {
                    e.printStackTrace();
                }

            }

        }
    }

【讨论】:

    【解决方案3】:

    不需要switch 语句和复杂的类层次结构。

    为了简化和缩短你的代码和计算简单和复杂的表达式(表示为String对象),你可以使用Java的JavaScript API,它是ScriptEngine类,它基本上模拟了一个JavaScript控制台。

    import javax.script.ScriptEngineManager;
    import javax.script.ScriptEngine;
    
    public class MyClass{
        public static void main(String[] args) throws Exception {
            // create a script engine manager
            ScriptEngineManager factory = new ScriptEngineManager();
            // create a JavaScript engine
            ScriptEngine engine = factory.getEngineByName("JavaScript");
            // evaluate JavaScript code from String
            System.out.println(engine.eval("(5+10)*2/3"));
        }
    }
    

    这将输出:10.0

    【讨论】:

    • 我比我更喜欢你的回答(使用ScriptEngine),所以我删除了它:)
    • 哦,我喜欢这个。这是一个 hack,但我喜欢它,很高兴知道它的存在。 ;)
    • 谢谢!我是最近才知道的。它可以减轻我们编写复杂内容的负担。 :)
    • 这应该是最重要的...拥有我对 ScriptEngine 的使用
    • 为了获得技术,Javascript 计算引擎可能不等同于 Java,但我认为这对提问者的问题有效,并且是一个非常好的解决方案!
    【解决方案4】:

    如何避免过多的代码重复很简单:

    Integer op1= Integer.parseInt(exp.substring(0, i);
    Integer op2=Integer.parseInt(exp.substring(i+1, exp.length()));
    if(exp.charAt(i)=='*')  {
                newResult=op1 * op2;
    } else 
    ....
    primeResult = newResult;
    System.out.println(primeResult);
    

    但是要使用任意嵌套级别做一些更通用、更健壮和更有用的事情,您应该使用一些真正的解析器。 For example.

    【讨论】:

      【解决方案5】:

      通过将变量与操作分开来缩短代码。这不会减少您的“if”语句,但会大大减少行号。

      在您了解树之前不要使用多个变量...我从未亲自使用过它们,但我认为“表达式树”是您所追求的。 (注意:我刚刚在 google 上查看过,是的,Expression Trees)

      【讨论】:

        【解决方案6】:

        要更改代码,您可以使用 switch 语句并将一些冗余代码放在 switch 之前或之后。

        int left = Integer.parseInt(exp.substring(0,i));
        int right = Integer.parseInt(exp.substring(i+1,exp.length()));
        switch(exp.charAt(i)){
            case '*':
                primeResult = left * right;
                break;
            case '/':
                ...
                break;
            case '+':
                ...
                break;
            case '-':
                ...
                break;
            default:
                ... // Error Handling.
        }
        System.out.println(primeResult);
        

        【讨论】:

        • 谢谢,太好了!它如何与 for 循环一起工作?说 for(i=0; i
        • 你需要计算出操作符在哪里,字符串的哪一部分构成了表达式的左右半边。我认为它不适用于for(i=0; i &lt; exp.length; i++),因为并非所有i 都代表运营商。你需要一个不同的 for 循环头。
        • 你可以做for循环检查if( isOperator( exp.substring(i, 1) ) ) { doOperation( exp, i ); }
        • @user2291971 我不知道像for(i=firstOperatorLoc; i &lt; exp. length; i = getNextOperatorLoc(exp, i)) 这样的东西,其中 firstOperatorLoc 是第一个操作员的位置,而 getNextOperatorLoc 找到下一个位置。但是,这不会执行操作顺序。或者您可以添加 @ShadowCreeper 提出的 if 语句。
        猜你喜欢
        • 2023-04-03
        • 1970-01-01
        • 1970-01-01
        • 2010-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多