-1

Please look at this piece of code:

       testFunction(input, a, b, 100, new FPFunction() {
                public double eval(double n) {
                        double whatShouldBeReturned = 2+n;
                        return whatShouldBeReturned;

                }
            }
    );

Just to let you know FPFunction is an interface and it's code is:

    interface FPFunction {
    double eval(double n);
}

the code above helps me to do some calculation on "2+x" funtion and that's it. if I wanted to change my function I should hardcode that into my program code for example to use it for "x*5+3" function I should change implementation of FPFunction to this:

      testFunction(input, a, b, 100, new FPFunction() {
                public double eval(double n) {

                        double whatShouldBeReturned = n*5+3;
                        return whatShouldBeReturned;

                }
            }
    );

and that is exactly what I don't like.I'd like to change the function via the user interface and not hardcode that. My assumption is that there is a way like this:

        testFunction(input, a, b, 100, new FPFunction() {
                public double eval(double n) {
                        String mytring="2+n";
                        double whatShouldBeReturned =AppropriateMethod(myString);
                        return whatShouldBeReturned;

                }
            }
    );
  • If you think this way is valid please tell me what could be "appropriateMethod(String s)"s body.
  • or if you have any other idea to do this please say.

by the way if you think the topic's name is not good please edit it to something you want.

  • 1
    No, there is no such method on String. You'll have to parse the expression yourself or use a library. – pvg Mar 24 '17 at 17:13
  • @pvg Thank's for answering.would you please go to details and me give some codes..that would be so nice. – Mohammad Ghanatian Mar 24 '17 at 17:16
  • So you want to pass a function as a parameter? If you are using java 8 you can read about lambda expressions. – Rumid Mar 24 '17 at 17:18
  • 1
    Try solution from this: http://stackoverflow.com/questions/2605032/is-there-an-eval-function-in-java – t4u Mar 24 '17 at 17:20
  • Possible duplicate of [Is there an eval() function in Java?](http://stackoverflow.com/questions/2605032/is-there-an-eval-function-in-java) – pvg Mar 24 '17 at 17:25
  • @t4u that's basically a dupe of this question but better and with a number of good answers so probably worth flagging as such. – pvg Mar 24 '17 at 17:26
  • @MohammadGhanatian the variable binding is something the js ScriptEngine can do, you just have to read the docs. – pvg Mar 24 '17 at 17:40

3 Answers3

0

Despite what belongs to good or not good approaches, you can for sure do that...

java is a powerfull language, so you need to 1st think if is a good design to implement what you are asking here and avoid your customers to kill themselves:

Haivng said this, to the answer:

java has an Engine that allows you to eval scripts, so if your equation is a string, and your engine is a javascript instance then you can offer such a "flexible"

consider this snippet:

public interface FPFunction {
    double eval(double n) throws NoSuchMethodException;
}

public class JavaEngImpl implements FPFunction {
    static String fx = "2+x";

    public static void main(final String[] args) throws NoSuchMethodException {
        final JavaEngImpl t = new JavaEngImpl();
        System.out.println(t.eval(2));
        System.out.println(t.eval(1));
        System.out.println(t.eval(5));
        // now cahnge the equation
        JavaEngImpl.fx = "3 * x";
        System.out.println("\nnow with: " + JavaEngImpl.fx);
        System.out.println(t.eval(2));
        System.out.println(t.eval(1));
        System.out.println(t.eval(5));
    }

    @Override
    public double eval(final double n) throws NoSuchMethodException {
        final ScriptEngineManager factory = new ScriptEngineManager();
        final ScriptEngine engine = factory.getEngineByName("JavaScript");
        Object ret = null;
        try {
            final String finalEquation = fx.replace("x", String.valueOf(n));
            ret = engine.eval(finalEquation);
        } catch (final ScriptException ex) {
            System.err.println(ex);
        }
        return (Double) ret;
    }
}

the output will be:

4.0

3.0

7.0

now with: 3 * x

6.0

3.0

15.0

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
0

You can try to solve your task with lambda expressions:

// functional interface
interface Operation
{  
  double perform(double d);
}  
class Main
{  
  // method that expects instance of the interface
  static double calculate(double d, Operation op)
  {  
    return op.perform(d);
  }  
  public static void main(String[] args)
  {  
    // lambda expression
    Operation n2 = (d) -> d + 2.;
    Operation n3 = (d) -> d + 3.;
    // method call
    double din = 1., result;
    result = calculate(din, n2);
    System.out.printf("operation: %s ; input: %f; result: %f%n", n2, din, result);
    result = calculate(din, n3);
    System.out.printf("operation: %s ; input: %f; result: %f%n", n3, din, result);
  } // end main
} // end class Main
Andrey
  • 2,503
  • 3
  • 30
  • 39
0

I can see two ways of doing this:

  1. Use a general purpose scripting engine within the JDK. For example:

    static ScriptEngineManager engineManager = new ScriptEngineManager();
    static ScriptEngine engine = engineManager.getEngineByName("nashorn");
    
    public static double eval(String expression, double n) throws NumberFormatException, ScriptException {
        String processedExpression = expression.replaceAll("n", Double.toString(n)); //Beware - this is a bad way of doing this
        return Double.parseDouble(engine.eval(processedExpression).toString())
    }
    
    public static void main(String... args) throws Throwable {
        System.out.println(eval("3*n+5", 10)); //Prints 35.0
    }
    

This works, but is error prone and requires a lot of care. You need to make sure that the substitution of n is valid, which is a bit tricky. For instance, the above quick and dirty code will evaluate "10n" with n=10 to "1010" due to the way in which it replaces n. You also need to avoid various invalid expressions such as "10;20", which would otherwise evaluate to 20.0.

  1. Use a library such as Javaluator
Malt
  • 28,965
  • 9
  • 65
  • 105
  • Thank you very much for answering.I read some posts.they were like what you said but there was a difference.and that was using javascript instead of nashorn.would you please tell me which one is better and what is the difference? – Mohammad Ghanatian Mar 24 '17 at 18:12
  • Also would you please tell me what is the good point in using javaluator instead of the first method? – Mohammad Ghanatian Mar 24 '17 at 18:16
  • @MohammadGhanatian Nashorn is the Java Javascript engine, there's no difference. – Malt Mar 24 '17 at 19:15
  • @MohammadGhanatian javaluator or a similar library would be better since it's designed for the task at hand. Using the JS engine, is hackish, and error prone. – Malt Mar 24 '17 at 19:16