4

如何将这个简单的计算器程序中的 switch/case 语句转换为跳转表。

import java.lang.*;
import java.util.*;

public class Calculator
{
    private int solution;
    private static int x, y, ops;
    private char operators;

    public Calculator()
    {
        solution = 0;
    }

    public int addition(int x, int y)
    {
       return x + y;
    }
    public int subtraction(int x, int y)
    {
       return x - y;
    }
    public int multiplication(int x, int y)
    {
       return x * y;
    }
    public int division(int x, int y)
    {
       solution = x / y;
       return solution;
    }

    public void calc(int ops){
         Scanner operands = new Scanner(System.in);

         System.out.println("operand 1: ");
         x = operands.nextInt();
         System.out.println("operand 2: ");
         y = operands.nextInt();

         System.out.println("Solution: ");

         switch(ops)
         {
             case(1):
               System.out.println(addition(x, y));
               break;
             case(2):
               System.out.println(subtraction(x, y));
               break;
             case(3):
               System.out.println(multiplication(x, y));
               break;
             case(4):
               System.out.println(division(x, y));
               break;
          }
    }
    public static void main (String[] args)
    {
      System.out.println("What operation? ('+', '-', '*', '/')");
      System.out.println(" Enter 1 for Addition");
      System.out.println(" Enter 2 for Subtraction");
      System.out.println(" Enter 3 for Multiplication");
      System.out.println(" Enter 4 for Division");

      Scanner operation = new Scanner(System.in);
      ops = operation.nextInt();

      Calculator calc = new Calculator();
      calc.calc(ops);


  }
}

老实说,我不知道跳转表到底是什么(在网上找不到任何解释),所以我不知道它与 switch/case 语句有何不同。

旁注:这段代码只处理整数,所以如果你除以 5/3,它会给你 1。我怎样才能轻松地将它更改为浮点数/双精度数。

4

4 回答 4

3

如前所述,跳转表是一组偏移量/指向函数的指针。与 C/C++ 不同,Java 并没有真正的函数指针(Java中的函数指针)

但是你可以假装,并以面向对象的方式来做。使用一种方法 (f) 定义基类 (Funky)。派生多个孩子,每个函数操作(+、-、*、/ 等)一个,并为每个孩子创建一个对象(毕竟它只是一个接口),并将该孩子存储到一个数组中类型(时髦)。

在表中查找操作,并在您的参数上调用该方法

例子:

定义一个基类,(或一个接口,让你更快乐?)。注意,如果你扩展一个类,你可以使用基类方法作为默认值(生成错误信息,或者抛出异常),

public class X
//or, public interface X
{
    //method
    Z fun(Z z1, Z z2)
    {
        //nothing to see here
    }
}

class X1 extends X //or, implements X
{
    public Z fun(Z z1, Z z2)
    {
        //variant1 stuff here
    }
}
...
public class Xn extends X //or, implements X
{
    public Z fun(Z z1, Z z2)
    {
        //variantn stuff here
    }
}

哦,您将需要实例,并将它们加载到数组(跳转表)中。

某些技术对某些语言来说是惯用的,跳转表更多的是系统的东西,而不是 Java 的东西,而不是真正的 Java 习惯用法。

于 2013-10-09T16:15:33.573 回答
0

well, i don't know what is a jump table, but if you wanna control another type of numbers, you can change of parameter for example you method:

public int addition(int x, int y)
    {
       return x + y;
    }

if you wanna Double-->

 public int addition(Double x, Double y)

but i strongly recommend you user the type Number every other class extens from Number.

Number.class

ex:

public static String numeroToLetra(Number num)
  {
    Integer numero = Integer.valueOf(num.intValue()); //int value 
    Double numero = Double.valueOf(num.doubleValue());........
}//so you can pass whatever type of number.
于 2013-10-09T16:05:09.647 回答
0

如果您正在使用支持 lambda 的 Java 版本,那么更符合实现为“跳转表”的要求的解决方案将使用实际的跳转表,该表将运算符代码映射到实现每个操作数。

这是一种令人愉悦的方式,不仅可以消除笨拙的 switch 语句,而且可以生成更易于维护和更易于扩展的代码。以后可以轻松添加未来的新操作数,而无需对 Calculator 实现进行任何更改。只需实现 new 运算符及其命名方法,并将其添加到跳转表中。您的计算器将自动支持新的操作数。

import com.google.common.collect.ImmutableMap;

import java.lang.*;
import java.util.*;

public class Calculator
{
    private static final Map<Integer,BinaryOperator<Integer>> evaluators = ImmutableMap.<Integer, BinaryOperator<Integer>>builder()
        .put(1, (Integer x, Integer y) -> new IntAddition().evaluateFor(x,y))
        .put(2, (Integer x, Integer y) -> new IntSubtraction().evaluateFor(x,y))
        .put(3, (Integer x, Integer y) -> new IntMultiplication().evaluateFor(x,y))
        .put(4, (Integer x, Integer y) -> new IntDivision().evaluateFor(x,y))
        .build();

    private static final Map<Integer,Nameable> names = ImmutableMap.<Integer, Nameable>builder()
        .put(1, () -> new IntAddition().getName())
        .put(2, () -> new IntSubtraction().getName())
        .put(3, () -> new IntMultiplication().getName())
        .put(4, () -> new IntDivision().getName())
        .build();

    private int solution;
    private static int x, y, ops;

    public Calculator()
    {
        solution = 0;
    }

    public void calc(int opcode)
    {
        Scanner operands = new Scanner(System.in);

        System.out.println("Enter operand 1: ");
        x = operands.nextInt();
        System.out.println("Enter operand 2: ");
        y = operands.nextInt();

        System.out.print("Solution: ");
        System.out.println(evaluators.get(opcode).evaluateFor(x, y));
    }

    public static void main(String[] args)
    {
        System.out.println("What operation?");
        for (Integer opcode : evaluators.keySet())
        {
            System.out.println(String.format(" Enter %d for %s", opcode, names.get(opcode).getName()));
        }

        Scanner operation = new Scanner(System.in);
        ops = operation.nextInt();

        Calculator calc = new Calculator();
        calc.calc(ops);
    }

    interface Nameable
    {
        String getName();
    }

    interface BinaryOperator<T>
    {
        T evaluateFor(T x, T y);
    }

    static class IntAddition implements BinaryOperator<Integer>, Nameable
    {
        IntAddition() { }

        public Integer evaluateFor(Integer x, Integer y)
        {
            return x + y;
        }

        public String getName()
        {
            return "Addition";
        }
    }
    static class IntSubtraction implements BinaryOperator<Integer>, Nameable
    {
        IntSubtraction() { }

        public Integer evaluateFor(Integer x, Integer y)
        {
            return x - y;
        }

        public String getName()
        {
            return "Subtraction";
        }
    }
    static class IntMultiplication implements BinaryOperator<Integer>, Nameable
    {
        IntMultiplication() { }

        public Integer evaluateFor(Integer x, Integer y)
        {
            return x * y;
        }

        public String getName()
        {
            return "Multiplication";
        }

    }
    static class IntDivision implements BinaryOperator<Integer>, Nameable
    {
        IntDivision() { }

        public Integer evaluateFor(Integer x, Integer y)
        {
            return x / y;
        }

        public String getName()
        {
            return "Division";
        }
    }
}
于 2019-02-15T22:10:09.833 回答
0

这是一个老问题,但我认为它仍然具有说明自Java 8以来您可以做什么的价值。基本上,您创建一个接口,其唯一目的是为操作数组提供类型,然后使用方法引用来填充操作数组。之后,您可以使用索引来选择正确的操作。我对 OP 的代码做了最小的修改,以便比较最简单:

import java.util.Scanner;


public class Calculator
{
    //
    // Create an interface to use as Type for
    // operations array.
    //
    private interface BinaryOperation {
        int performOperation(int a, int b);
    }
    //
    // Array has one unused element to make coding easier
    // and use operation as a direct index.
    // You can replace with 4 element array easily.
    //
    BinaryOperation[] operations = new BinaryOperation[5];

    private int solution;
    private static int x, y, ops;
    private char operators;

    public Calculator()
    {
        solution = 0;
        //
        // Initialize jump table using method references.
        //
        operations[1] = this::addition;
        operations[2] = this::subtraction;
        operations[3] = this::multiplication;
        operations[4] = this::division;
    }

    public int addition(int x, int y)
    {
        return x + y;
    }
    public int subtraction(int x, int y)
    {
        return x - y;
    }
    public int multiplication(int x, int y)
    {
        return x * y;
    }
    public int division(int x, int y)
    {
        solution = x / y;
        return solution;
    }

    public void calc(int ops){
        Scanner operands = new Scanner(System.in);

        System.out.println("operand 1: ");
        x = operands.nextInt();
        System.out.println("operand 2: ");
        y = operands.nextInt();

        System.out.println("Solution: ");
        //
        // Call binary operation through jump table
        //
        System.out.println(operations[ops].performOperation(x, y));
    }
    public static void main (String[] args)
    {
        System.out.println("What operation? ('+', '-', '*', '/')");
        System.out.println(" Enter 1 for Addition");
        System.out.println(" Enter 2 for Subtraction");
        System.out.println(" Enter 3 for Multiplication");
        System.out.println(" Enter 4 for Division");

        Scanner operation = new Scanner(System.in);
        ops = operation.nextInt();

        Calculator calc = new Calculator();
        calc.calc(ops);


    }
}
于 2018-10-20T22:33:11.667 回答