Im trying to to create a simple 4 function calculator using a jump table without switch case or if/else statements. I understand I can create the jump table via function pointers but I am kindda blanking out. I've started with the addition and subtraction part of the program but am trying to grasp the design/strategy to use. I am also getting an error when putting the method in the array, so far this is what i have:
public class Calculator {
public abstract class Functor{
abstract double Compute(double op1, double op2);
}
class Addition extends Functor
{
public double Compute(double op1, double op2){ return op1 + op2;}
}
class Subtraction extends Functor
{
public double Compute(double op1, double op2){ return op1 - op2;}
}
public static void main(String[] args) {
Functor add = new Addition(); // Problem here
Functor sub = new Subtraction(); // and here
}
}
any help or ideas for the step in the right direction is greatly appreciated!
thanks in advance!
Let's try this instead:
public enum Operation {
PLUS("+") {
double apply(double x, double y) { return x + y; }
},
MINUS("-") {
double apply(double x, double y) { return x - y; }
},
TIMES("*") {
double apply(double x, double y) { return x * y; }
},
DIVIDE("/") {
double apply(double x, double y) { return x / y; }
};
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
#Override public String toString() {
return symbol;
}
abstract double apply(double x, double y);
}
This will only work if you're using Java 5 or later, which has generics and enums. What this does is it gives you a static set of operations. You access them by typing Operation.PLUS or Operation.MINUS, etc.
To test it try this:
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
for (Operation op : Operation.values())
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
For more information consult Effective Java, Second Edition by Joshua Bloch.
It's worth pointing out that Java has no notion of "function pointers". Rather you simple write an interface and write a class that implements that interface. The correct class to use is selected at runtime; hence, that is a "jump table" but it's hidden behind the semantics of object-oriented programming. This is known as polymorphism.
While that's decent (aside from not having constructors that work right) I'd do it different, using anonymous classes.
abstract class Functor {
public abstract double compute(double a, double b);
public static void main(String[] args) {
Functor add = new Functor() {
// defining it here is essentially how you do a function pointer
public double compute(double a, double b) { return a + b; }
};
Functor subtract = new Functor() {
public double compute(double a, double b) { return a - b; }
};
System.out.println(add.compute(1.0,2.0));
System.out.println(subtract.compute(1.0,2.0));
}
}
Result:
C:\Documents and Settings\glowcoder\My Documents>java Functor
3.0
-1.0
C:\Documents and Settings\glowcoder\My Documents>
You don't have any constructors to pass in any arguments to your sub-classes, I don't understand how you think opt1 and opt2 are going to be set without any constructors with those as parameters. This is not correct Java code right now.
Related
I was reading a java book, where I came across this statement:
So, every subroutine is contained either in a class or in an object
I'm really confused why does it say "class or in an object"
I would like some explanation.
Let's try this example
public class Demo {
public static void classMethod() {
System.out.println("Call to static method");
}
public void objectMethod() {
System.out.println("Call to object method");
}
public static void main(String[] args) {
Demo demo = null;
demo.classMethod();
//demo.objectMethod();// throws NPE if uncommented
}
}
This code will work (even if the demo variable is null) because static method classMethod is contained within the class Demo. The commented line will throw a NullPointerException because the method objectMethod is not contained in the class but in the object so will need an instance of Demo class to call it.
Subroutine is a method written inside a class. We use them to do various tasks. That statement states that these methods/subroutines are written in an object or a class.
If we have an object instantiated, it will create new methods for every non-static method for that object which were defined in the class of the object. Hence those non-static methods/subroutines are in the object.
But if the class is a static class, we can't have any objects from it. But we can use subroutines/methods of that class. So, they are in a Class
That's what your statement says.
EDIT:
I thought to give an example for this.
public class ExampleClass {
public String getNonStaticString() {
return "This String is From Non-Static Method";
}
public static String getStaticString() {
return "This String is From Static Method"
}
}
Then, if you need to get the static String, all you have to do is
String staticString = ExampleClass.getStaticString();
Note that I havn't created an object from the ExampleClass Here. I just used the method.
But, if you need to get the String from the non-static method, you should instantiate an object first.
ExampleClass exampleObject = new ExampleClass();
String nonStaticString = exampleObject.getNonStaticString();
static methods also known as class method. Static method associated only with the class and not with any specific instance of that class(object).
So, every subroutine is contained either in a class or in an object
The statement is technically not 100% correct.
First of all, subroutines in java are commonly called methods. The following two terms are often used interchangeably:
Method: A subroutine working with an object instance, this.
Function: A subroutine not working with an object instance.
Here is an example scenario which should you get an idea what that means:
public class Circle {
//region static code
//we cannot call "this" in a static context, main(String[]) is no exception here
public static void main(String[] args) {
Circle a = new Circle(0, 0, 10);
Circle b = new Circle(10, 10, 2);
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("circumference of a = " + a.getCircumference());
System.out.println("circumference of b = " + b.getCircumference());
System.out.println("area of a = " + a.getArea());
System.out.println("area of b = " + b.getArea());
System.out.println("distance of a, b = " + distance(a, b));
System.out.println("a, b intersect = " + (intersects(a, b) ? "yes" : "no"));
}
//we cannot call "this" in a static context, but we have the circles a, b as parameters we can use to calculate their distance
public static double distance(Circle a, Circle b) {
return Math.sqrt(squared(a.x - b.x) + squared(a.y - b.y));
}
//we cannot call "this" in a static context, but we have the circles a, b as parameters we can use to check for an intersection
public static boolean intersects(Circle a, Circle b) {
return a.radius + b.radius > distance(a, b);
}
//we cannot call "this" in a static context, but we have the number x as parameter we can use to calculate the square of
public static double squared(double x) {
return x * x;
}
//we cannot call "this" in a static context, but we have the number radius as parameter we can use to check if its value is in range
public static void checkRadius(double radius) {
if(radius < 0) {
throw new IllegalArgumentException("radius must be >= 0");
}
}
//endregion
//region member / instance code
private double x;
private double y;
private double radius;
public Circle(double x, double y, double radius) {
checkRadius(radius);
this.x = x;
this.y = y;
this.radius = radius;
}
//region getters and setters
//we may refer to the instance variables with or without "this", sometimes it is necessary to clarify - see: setX(double)
public double getX() {
return x;
}
//we may refer to the instance variables with or without "this", but in this case we have two variables with name "x"
//if we write "x", the parameter is taken. for the circle's x coordinate, we need to clarify with "this.x"
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
checkRadius(radius);
this.radius = radius;
}
//endregion
//we may refer to the instance variables with or without "this", sometimes it is necessary to clarify - see: setX(double)
public double getCircumference() {
return 2 * Math.PI * radius;
}
public double getArea() {
return Math.PI * squared(radius);
}
//we may refer to the instance variables with or without "this", sometimes it is necessary to clarify - see: setX(double)
#Override
public String toString() {
return "circle at [" + x + ", " + y + "] with radius " + radius;
}
//endregion
}
Output:
a = circle at [0.0, 0.0] with radius 10.0
b = circle at [10.0, 10.0] with radius 2.0
circumference of a = 62.83185307179586
circumference of b = 12.566370614359172
area of a = 314.1592653589793
area of b = 12.566370614359172
distance of a, b = 14.142135623730951
a, b intersect = no
Can you help me find my error?
I'm trying to use these two methods here but my output is not working.
class Nine {
public static void Nine(String[] args) {
int x,y,z;
y = 3;
x = 7;
z = addEm(a, b);
System.out.println("answer= " +x);
}
public static addEm (double a, double b){
int c;
c = a+b;
}
}
Actually there are a lot of error in your code:
z=addEm(a, b);
here a and b are meaningless, you should use z=addEm(y,x); (if your intent is to sum three with seven)
System.out.println("answer= " +x);
I guess that you want to show the the results of the sum, therefore you should print z (and not x), so you should substitute with System.out.println("answer= " +z);
public static addEm (double a, double b) {
Here you missed the return type, and you need to consider also the type of parameters a and b. Since y,x and z are int, it is better if also a and b are int, and therefore specify also the return type as int:
public static int addEm (int a, int b) {
Or you can declare everything (y,x,z,a,b and return type) as a double: the important here is that they should be all of the same type. Moreover you miss also the return statement of the function addEm, that summarizing becomes:
public static int addEm (int a, int b)
{
int c;
c=a+b;
return c;
}
And finally also the function
public static void Nine(String[] args)
it is not right named for an entry point: its names should be main.
So in conclusion, if you apply all the fix (by modifying as less as possible your original code) a code that compile, run and works following some 'logic' is:
class Nine {
public static void main(String[] args) {
int x, y, z;
y = 3;
x = 7;
z = addEm(y, x);
System.out.println("answer= " + z);
}
public static int addEm(int a, int b) {
int c;
c = a + b;
return (c);
}
}
Man, this is a very basic java lesson:
every prog need an entry point, which is in java:
public static void main(String args[]){}
And then your code will execute.
You're passing arguments a and b to addEm, but those variables aren't initialized. I'm expecting you wanted to pass x and y instead.
class Nine
{
public static void Nine(String[] args)
{
int x,y,z;
y=3;
x=7;
z=addEm(x, y);
System.out.println("answer= " +x);
}
public static addEm (double a, double b)
{
int c;
c=a+b;
}
}
Your code will not work because your addEm method does not have any return type. In addition, the method you wrote takes Double params but while using you are trying to pass int to it. You also do not have any main method. I am assuming you misspelled or misunderstood the main method so below is the code which should work
class Nine
{
public static void Main(String[] args)
{
int x,y,z;
y=3;
x=7;
z=addEm(x, y);
System.out.println("answer= " + x);
}
public static int addEm (int a, int b)
{
int c;
c=a+b;
return c;
}
}
How do I make the switch/case statement in this simple Calculator program into a jump table.
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);
}
}
To be completely honest, I don't know exactly what a jump table is (couldn't find any explanations online) so I don't know how it differs from a switch/case statement.
Side Note: This code only deals with integers so if you divide 5/3 its gives you 1. How can I easily change it to take floats/doubles.
As mentioned, a jump table is an array of offsets/pointers to functions. Unlike C/C++, Java doesn't really have function pointers (Function Pointers in Java)
But you can pretend, and do it the object oriented way. Define a base class (Funky) with one method (f). Derive mutiple children, one for each of your functional operations (+,-,*,/, etc), and create a single object for each child (it is just an interface, after all), and store that child into an array of type (Funky).
Lookup the operation in the table, and call the method on your arguments
Example:
Define a base class, (or an interface, which makes you happier?). Note that if you extend a class, you can use the base class method as a default (generate an error message, or throw an exception),
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
}
}
Oh, and you will need instances, and load them into an array (the jumptable).
There are certain techniques which are idiomatic to certain languages, and jumptables are more of a systems thing and less of a Java thing, not really a Java idiom.
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.
This is an old question, but I think it still has value for illustrating what you can do since Java 8. Basically, you create an interface whose sole purpose is to provide a type for an operations array and then you use method references to populate the operations array. After that, you can use the index to select the proper operation. I made minimal modifications to the OP's code such that the comparison is easiest:
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);
}
}
If you're working with a version of Java that supports lambdas, a solution that is more true to the requirement to implement as a "jump table" would use an actual jump table, one that maps operator codes to lambda expressions that implement each the operands.
This is a pleasing way not only to eliminate clunky switch statements, but to produce more maintainable and more easily extensible code. Future new operands can easily be added later without making any changes to the Calculator implementation. Simply implement the new operator and its naming method, and add it to the jump tables. Your Calculator will automatically support the new operand.
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";
}
}
}
I was wondering how I could call getJD() within getToD and keep the parameters intact,(or temporarily set the parameters as variables in main and call the variables to the method).
The parameters are going to be input using the scanner class later in the main method.
import static java.lang.Math.*;
public class jdMethods
{
public static double getJD(double y, double m, double d){
if (m<=2.0){
y--;
m += 12.0;
}
double a=floor(y/100.0);
return (365.25*(y+4716.0))+(30.6001*(m+1))+d+(2.0-a+floor(a/4.0))-1524.5;
}
public static double getToD(int h, int m, int s)
{
double a = getJD(a, a, a) + ((h-12)/24) + (m/1440) + (s/86400);
return a;
}
}
Edited for clarity.
It's not perfectly clear on what you are trying to do, but I assumed that you just want to save the result of your first getJD() and to use the result within your getToD(), so I made a private _jd and created a setter and getter for it.
import static java.lang.Math.*;
public class jdMethods
{
private double _jd;
public double getJD(){
return _jd;
}
public void setJD(double y, double m, double d){
if (m<=2.0){
y--;
m += 12.0;
}
double a=floor(y/100.0);
_jd = (365.25*(y+4716.0))+(30.6001*(m+1))+d+(2.0-a+floor(a/4.0))-1524.5;
}
public double getToD(int h, int m, int s)
{
double a = getJD() + ((h-12)/24) + (m/1440) + (s/86400);
return a;
}
}
So here is how you call it:
jdMethods testRun = new jdMethods();
testRun.setJD(1,2,3);
System.out.println(testRun.getToD(3, 2, 1));
All those parameters will be intact since you are using double and int, those are not Object s so it's value is copied when passed to a function, unlike Object s that a reference to it is passed to the function.
About your code, undefined variable a won't let it compile:
double a = getJD( a, a, a ) + ((h-12)/24) + (m/1440) + (s/86400);
I don't get what you are trying to do there, remember that a from getJD method is not the same a into getToD.
I read the next answer about passing function as parameter.
Still, I don't get the idea. My function can get any function: sin(x), cos(x), etc.
As I understood, I can create an interface, for example:
public interface functionI<T> {
}
that would wrap It.
Now I have my function:
public void needToDo(functionI<Integer> a, int x0Par, int hPar){
}
(needToDo, for example, need to substitue the x of the function n x0par and hPar, and find the Max. If I got sin(x), I need to find the max of sin(x0Par) and (sin(hPar)).
I didn't understand how I use it in my function. How will I know what to do when I got the function, that can be anything (polynomial, sin(x), and so on)
Something like this:
public interface Function1<RESULT,INPUT> {
RESULT call(INPUT input);
}
public class Sin implements Function1<Double,Double> {
public static final Sin instance = new Sin();
private Sin() {
}
public Double call(Double x) {
return Math.sin(x);
}
}
public Double needToDo(Function1<Double,Double> aFunction, Double x0Par, Double hPar) {
Double d1 = aFunction.call(x0Par);
Double d2 = aFunction.call(hPar);
return d1 > d2 ? d1 : d2;
}
public static void main(String[] args) {
Double x0Par = 10.2;
Double hPar = 1.9;
Double ret = needToDo(Sin.instance, x0Par, hPar);
System.out.println(ret);
}
It doesn't quite work like that; you cannot pass arbitrary functions as parameters in Java, instead you pass objects which have specific, often generic sounding, functions.
So you could define a MathOperation interface, which has an execute method, taking a double and returning a double.
public interface MathOperation {
double execute(double x);
}
and then you can create
public class Sin implements MathOperation {
public double execute(double x) { return Math.sin(x); }
}
and have a function that uses it like
public void needToDo(MathOperation op, double x) {
System.out.println(op.execute(x));
}
You could create an on-the-fly function for needToDo like
...
needToDo(new MathOperation() {
public double execute(double x) { return x * 2.0; }
});
...
But you can't pass Math.sin as a parameter. There are reflection tricks you can do, but that's another issue.