de.congrace.exp4j fails on multiple arguments for a CustomFunction - java

i am trying to add a custom function that sums number to a ExpressionBuilder
This is the java code:
package com.sapiens.bdms.drools.exe.helper.FuncServiceTrial;
import com.sapiens.bdms.drools.exe.helper.Functions;
import de.congrace.exp4j.*;
import java.util.ArrayList;
import java.util.Collection;
public class FormulaInterpreter {
public double interpret(String formula) throws UnparsableExpressionException, UnknownFunctionException, InvalidCustomFunctionException {
Collection<CustomFunction> customFunctions = new ArrayList<CustomFunction>();
customFunctions.add(new CustomFunction("SUM") {
#Override
public double applyFunction(double[] doubles) {
Double res = 0.0;
for (double aDouble : doubles) {
res += aDouble;
}
return res;
}
});
Calculable calc = (Calculable) new ExpressionBuilder(formula).withCustomFunctions(customFunctions).build();
return calc.calculate();
}
public static void main(String[] args) throws UnknownFunctionException, UnparsableExpressionException, InvalidCustomFunctionException {
FormulaInterpreter formulaInterpreter = new FormulaInterpreter();
double res = formulaInterpreter.interpret("SUM(2,4,4)");
System.out.println(res);
}
}
but it prints out "2" instad of 10

Can you try this constructor telling exp4j how many arguments your function should have:
new CustomFunction("SUM",3)
as described in the API Docs: http://www.objecthunter.net/exp4j/apidocs/de/congrace/exp4j/CustomFunction.html
Here is a working JUnit test case:
#Test
public void testCustomFunction21() throws Exception {
CustomFunction sumFunc = new CustomFunction("SUM",3) {
#Override
public double applyFunction(double[] doubles) {
Double res = 0.0;
for (double aDouble : doubles) {
res += aDouble;
}
return res;
}
};
Calculable calc = (Calculable) new ExpressionBuilder("SUM(2,4,4)").withCustomFunction(sumFunc).build();
assertTrue(10d == calc.calculate());
}
Hope this helps,
Frank

Related

How to apply a value from one method to another?

Cant set radius to count square: there're two methods, but how to force Java to count my square through radius that is random from randomNumber() ?
public class Figure {
public double randomNumber() {
return Math.random() * 11;
}
public double circleArea () {
return Math.PI*Math.pow(r,2); //how to assign a variable r in order to connect to randomNumber()??
}
public static void main(String[] args) {
Figure figure = new Figure();
System.out.println("r="+figure.randomNumber()+", s="+figure.circleArea());
}
}
Few different ways. You need to choose what works best for your scenario:
You can call the method from where required.
public double circleArea () {
return Math.PI*Math.pow(randomNumber(),2);
}
You can change the method to include a variable.
public double circleArea (double r) {
return Math.PI*Math.pow(r,2);
}
public static void main(String[] args) {
Figure figure = new Figure();
double r = figure.randomNumber();
System.out.println("r=" + r + ", s=" + figure.circleArea(r));
}
All you have to do is defining a private variable that holds the r value
public class Figure {
private double r;
public double randomNumber() {
r = Math.random() * 11;
return r;
}
public double circleArea () {
return Math.PI*Math.pow(r,2); //how to assign a variable r in order to connect to randomNumber()??
}
public static void main(String[] args) {
Figure figure = new Figure();
System.out.println("r="+figure.randomNumber()+", s="+figure.circleArea());
}

Check and correct my code. (I'm a beginner)

Can someone please help me correct my code ? It is created to calculate housing loan (UMI), the coding is correct but it doesn't show the output completely. After "Enter loan duration", it shows a box. Also is there another way to set the variables in class Variables ?
package assignment.pkg2;
import java.util.Scanner;//for Scanner
import java.text.DecimalFormat;//for using decimal format
class Variables{ //set the variables
private double p, r, n;
public void setVarP (double amount){
this.p = amount;
}
public void setVarR (double rate){
this.r = rate;
}
public void setVarN (int duration){
this.n = duration;
}
public double getVarP(){
return p;
}
public double getVarR(){
return r;
}
public double getVarN(){
return n;
}
}
class EMIcalc{ //the calculating part
private double monthlyPay, pow;
Variables var = new Variables();
Scanner scanner = new Scanner(System.in);
public void getPay(){
pow = Math.pow (1+(var.getVarR()/12), - var.getVarN());
monthlyPay = var.getVarP() * ( (var.getVarR()/12) / (1 - pow) );
DecimalFormat Dformat = new DecimalFormat("##.##");
System.out.println(Dformat.format(monthlyPay));
}
}
public class Assignment2 {
public static void main(String[] args) {
Variables var1 = new Variables();
EMIcalc calc = new EMIcalc();
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your loan amount");
var1.setVarP(scanner.nextDouble());
System.out.println("Enter interest rate");
var1.setVarR(scanner.nextDouble());
System.out.println("Enter loan duration");
var1.setVarN(scanner.nextInt());
calc.getPay();
}
}
Your are setting the values into var1, but the calc looks at its internal var field, which is a different object. You could just replace var1.set... by calc.var.set....
Or you could merge your Variables and EMIcalc classes into one.
Are you looking for this?
import java.text.DecimalFormat;
import java.util.Scanner;
class Variables { //set the variables
private double p, r, n;
public double getVarP() {
return p;
}
public void setVarP(double amount) {
this.p = amount;
}
public double getVarR() {
return r;
}
public void setVarR(double rate) {
this.r = rate;
}
public double getVarN() {
return n;
}
public void setVarN(int duration) {
this.n = duration;
}
}
class EMIcalc { //the calculating part
Variables var = new Variables();
Scanner scanner = new Scanner(System.in);
private double monthlyPay, pow;
public void getPay() {
pow = Math.pow(1 + (var.getVarR() / 12), -var.getVarN());
monthlyPay = var.getVarP() * ((var.getVarR() / 12) / (1 - pow));
DecimalFormat Dformat = new DecimalFormat("##.##");
System.out.println(Dformat.format(monthlyPay));
}
}
public class Assignment2 {
public static void main(String[] args) {
EMIcalc calc = new EMIcalc();
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your loan amount");
calc.var.setVarP(scanner.nextDouble());
System.out.println("Enter interest rate");
calc.var.setVarR(scanner.nextDouble());
System.out.println("Enter loan duration");
calc.var.setVarN(scanner.nextInt());
calc.getPay();
}
}
PS: Try your assignments by yourself.

NullPointerException when trying to run PostFixCalculator in Java

I have gotten my code to work to the extent that it can compile and run but now I get exceptions at two different places as follows:
Exception in thread "main" java.lang.NullPointerException
at PostFixCalculator.storeOperand(PostFixCalculator.java:97)
at CalcTest.main(CalcTest.java:17)
...I am not sure at all what is wrong. The first error is in the code that follows at
myStack.push(operand);
But I am so lost as to where to go from here...
import java.util.*;
public class PostFixCalculator {
private DoubleStack<Double> myStack;
private ArrayList<Double> evalList;
//private Map<String, Operator> operatorMap;
Map<String, Operator> operatorMap = new HashMap<String, Operator>();
public PostFixCalculator () {
Map<String, Operator> operatorMap = new HashMap<String, Operator>();
operatorMap.put("+", new AddOp());
operatorMap.put("add", new AddOp());
operatorMap.put("-", new SubOp());
operatorMap.put("sub", new SubOp());
operatorMap.put("/", new DivOp());
operatorMap.put("div", new DivOp());
operatorMap.put("*", new MultOp());
operatorMap.put("mult", new MultOp());
operatorMap.put("=", new PrintOp());
operatorMap.put("print", new PrintOp());
}
public class AddOp implements Operator {
public AddOp () {
}
public int numArgs () {
return 2;
}
public double eval (List<Double> args) {
double a = args.get(0);
double b = args.get(1);
double sum = a + b;
return sum;
}
}
public class SubOp implements Operator {
public SubOp () {
}
public int numArgs () {
return 2;
}
public double eval (List<Double> args) {
double a = args.get(0);
double b = args.get(1);
double difference = a - b;
return difference;
}
}
public class DivOp implements Operator {
public DivOp () {
}
public int numArgs () {
return 2;
}
public double eval (List<Double> args) {
double a = args.get(0);
double b = args.get(1);
double quotient = a / b;
return quotient;
}
}
public class MultOp implements Operator {
public MultOp () {
}
public int numArgs () {
return 2;
}
public double eval (List<Double> args) {
double a = args.get(0);
double b = args.get(1);
double product = a * b;
return product;
}
}
public class PrintOp implements Operator {
public PrintOp () {
}
public int numArgs () {
return 1;
}
public double eval (List<Double> args) {
System.out.println(myStack.pop());
return 1;
}
}
public void storeOperand (double operand) {
myStack.push(operand);
}
public void evalOperator (String operator) {
Operator o = operatorMap.get(operator);
ArrayList<Double> evalList = new ArrayList<Double>();
if (o.numArgs() == 2) {
double a = myStack.pop();
double b = myStack.pop();
evalList.add(a);
evalList.add(b);
}
else {
double a = myStack.pop();
evalList.add(a);
}
double answer = o.eval(evalList);
myStack.push(answer);
}
}
Make sure you're importing everything you are using. At the top of your file, add:
import java.util.ArrayList;
If you're using Eclipse you can press Ctrl-Shift-O to fix your imports.
You are still missing the following imports:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Then check the remaining errors related to your custom types.

SumAggregation using generics types

I want to do a sum for all over a Collection of numbers. But I want to indicate the return number type. For example I want to do the sum of a double collection, but I want to get back an Integer.
I want to have something like this SumAggregator. Here is the code I develop, but I have a Cast problem.
public class SumAggregator<N1 extends Number, N2 extends Number> {
public SumAggregator() {
}
public N2 sum(Collection<? extends N1> list){
Double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return (N2) sum;
}
}
If I want to do SumAggregator<Double, Double> I don't have any problem. But if I want to do SumAggregator<Double, Integer>, once I run I get the following exception:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
Any idea of how to solve this?
Not exactly what you wanted but you could do something like:
interface DoubleConverter<N extends Number) {
N2 convert(double d);
}
And add a constructor to your SumAggregator:
private final DoubleConverter<N2> converter;
public SumAggregator(DoubleConverter<N2> converter) {
this.converter = converter;
}
And your method would look like:
public N2 sum(Collection<? extends N1> list){
double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return converter.convert(sum);
}
finally, you would create one with:
SumAggregator<Double, Integer> a = new SumAggregator<> (new DoubleConverter<Integer>() {
public Integer convert(double d) { return (int) d; }
});
Finally, you could add some helper methods in the DoubleConverter interface:
DoubleConverter<Integer> INTEGER = new DoubleConverter<Integer>() {
public Integer convert(double d) { return (int) d; }
}
so the calling code can use:
SumAggregator<Double, Integer> a = new SumAggregator<> (DoubleConverter.INTEGER);
This is the solution I choose:
public class SumAggregator<N1 extends Number, N2 extends Number> {
private final NumberConverter<N2> converter;
public SumAggregator(NumberConverter<N2> converter) {
this.converter = converter;
}
public N2 sum(Collection<? extends N1> list){
double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return converter.convert(sum);
}
}
And then:
public interface NumberConverter<N2> {
N2 convert(Number d);
NumberConverter<Short> SHORT = new NumberConverter<Short>() {
public Short convert(Number d) {
return d.shortValue();
}
};
NumberConverter<Integer> INTEGER = new NumberConverter<Integer>() {
public Integer convert(Number d) {
return d.intValue();
}
};
NumberConverter<Double> DOUBLE = new NumberConverter<Double>() {
public Double convert(Number d) {
return d.doubleValue();
}
};
NumberConverter<Float> FLOAT = new NumberConverter<Float>() {
public Float convert(Number d) {
return d.floatValue();
}
};
NumberConverter<Long> LONG = new NumberConverter<Long>() {
public Long convert(Number d) {
return d.longValue();
}
};
}

Assistance Required, Developing Java Based Scripting Language?

I have just begun working on a programming language called XScript. It is designed so that I can run it from a Java application, but also re-program it through a java application. The idea being so that I can create virtual computers in games or a program that develops itself over time. So far I have the following code. I understand there may need to be an alteration to the name due to proprietary software, but for now it is fine.
The Artificial Main Class:
import com.x.lang.XLoader;
public class Main {
public static void main(String[] args) {
XLoader xl = new XLoader();
xl.exec("/Users/Nathan/Desktop/XScript/test.xls");
}
}
The XLoader (Loads and executes the XScript):
package com.x.lang;
import java.io.File;
import com.x.lang.object.XObject;
public class XLoader {
XObject xo;
public String fileLocation;
public void exec(String fl) {
fileLocation = fl;
XObject xo = new XObject(new File(fileLocation));
xo.exec();
}
}
The XCommandHub Where the Language Key Functions are Stored:
package com.x.lang;
import com.x.lang.keyword.Print;
import com.x.lang.keyword.Set;
import com.x.lang.object.XCommand;
import com.x.lang.object.XObject;
public class XCommandHub {
public XCommand xc[] = new XCommand[2];
public XCommandHub(XObject x) {
xc[0] = new Print(x);
xc[1] = new Set(x);
}
public XCommand getCommand(String s) {
for (int i = 0; i < 2; i++) {
if (xc[i].getCommandName() == s) {
return xc[i];
}
}
return null;
}
}
The XCommand Class Defining The Keywords:
package com.x.lang.object;
public abstract class XCommand {
private String commandName;
public XObject xobject;
public XCommand (String cn, XObject x) {
commandName = cn;
commandName += ": ";
xobject = x;
}
public abstract void exec(XVar xv);
public String getCommandName() {
return commandName;
}
}
The XVar Class Defining All Variables:
package com.x.lang.object;
public class XVar {
private String var1;
public String name;
public XVar(String s) {
var1 = s;
}
public String getStringValue() {
if (this.var1 != null) {
return var1;
}
return " ";
}
public int getIntValue() {
if (this.var1 != null) {
return Integer.parseInt(var1);
}
return 0;
}
public void setName(String s) {
name = s;
}
}
The XObject Class Actual Executing the Commands:
package com.x.lang.object;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import com.x.lang.XCommandHub;
public class XObject {
public XVar xvars[] = new XVar[150];
public int varCount = 0;
public File f;
XCommandHub x;
public XObject (File file) {
f = file;
x = new XCommandHub(this);
}
public void addVar(XVar var, String name) {
xvars[varCount] = var;
xvars[varCount].setName(name);
varCount++;
}
public XVar getVar(String varName) {
for (int i = 0; i < varCount; i++) {
if (xvars[i].name == varName) {
return xvars[i];
}
}
return null;
}
public void exec() {
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
for (int i = 0; i < 2; i++) {
if (sCurrentLine.startsWith(x.xc[i].getCommandName()))
try {
x.getCommand(x.xc[i].getCommandName()).exec(new XVar(sCurrentLine.split(": ")[1]));
} catch (ArrayIndexOutOfBoundsException e) {
x.getCommand(x.xc[i].getCommandName()).exec(new XVar(" "));
}
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
The Two Classes Defining The Commands I Have Programmed So Far:
package com.x.lang.keyword;
import com.x.lang.object.XCommand;
import com.x.lang.object.XObject;
import com.x.lang.object.XVar;
public class Print extends XCommand {
public Print(XObject x) {
super("print", x);
}
#Override
public void exec(XVar xv) {
if (xv.getStringValue().startsWith("%")) {
try {
System.out.println(xobject.getVar(xv.getStringValue().substring(1)).getStringValue());
} catch (NullPointerException e) {
System.out.println(xv.getStringValue());
}
}
else {
System.out.println(xv.getStringValue());
}
}
}
package com.x.lang.keyword;
import com.x.lang.object.XCommand;
import com.x.lang.object.XObject;
import com.x.lang.object.XVar;
public class Set extends XCommand {
public Set(XObject x) {
super("set", x);
}
#Override
public void exec(XVar xv) {
String[] add = xv.getStringValue().split("=");
xobject.addVar(new XVar(add[1]), add[0]);
}
}
From what I have programmed so far I have tried to give the user the ability to print a variable that they have declared in the code. A basic .xls (X Language Script) might look something like this:
set: x=Hello StackOverflow
print: This was programmed in XScript!
print:
print: %x
However, there is a NullPointerException in the print class when I try and retrieve the variable x from the array. The program returns "%x" rather than "Hello StackOverflow", because I have deliberately caught the exception, however I do not know how it came about in the first place.
Thanks
Doctor_N
Your code will never find the variable it is looking for:
public XVar getVar(String varName) {
for (int i = 0; i < varCount; i++) {
if (xvars[i].name == varName) {
return xvars[i];
}
}
return null;
}
This function will almost always return null since you are comparing strings using == and not using .equals. == compares references (memory addresses) and it is highly unlikely that the parameter and the string you are comparing against will point to the same location. Due to this, you almost always return null.
Because of that, this line will always cause a NullPointerException:
System.out.println(xobject.getVar(xv.getStringValue().substring(1)).getStringValue());
This is because you are effectively calling getStringValue() on null.
I suggest changing the if to:
if(xvars[i] != null && xvars[i].name.equals(varName)) {
...
}

Categories

Resources