Giter Site home page Giter Site logo

ezylang / evalex Goto Github PK

View Code? Open in Web Editor NEW
956.0 42.0 263.0 768 KB

EvalEx is a handy expression evaluator for Java, that allows to evaluate simple mathematical and boolean expressions.

Home Page: https://ezylang.github.io/EvalEx/

License: Apache License 2.0

Java 100.00%
expression-evaluator expression-parser java

evalex's Introduction

EvalEx - Java Expression Evaluator

Build Quality Gate Status Security Rating Vulnerabilities Maven Central

For a complete documentation, see the documentation site.

EvalEx is a handy expression evaluator for Java, that allows to parse and evaluate expression strings.

Key Features:

  • Supports numerical, boolean, string, date time, duration, array and structure expressions, operations and variables.
  • Array and structure support: Arrays and structures can be mixed, building arbitrary data structures.
  • Supports the NULL datatype.
  • Uses BigDecimal for numerical calculations.
  • MathContext and number of decimal places can be configured, with optional automatic rounding.
  • No dependencies to external libraries.
  • Easy integration into existing systems to access data.
  • Predefined boolean and mathematical operators.
  • Predefined mathematical, boolean and string functions.
  • Custom functions and operators can be added.
  • Functions can be defined with a variable number of arguments (see MIN, MAX and SUM functions).
  • Supports hexadecimal and scientific notations of numbers.
  • Supports implicit multiplication, e.g. 2x or (a+b)(a-b) or 2(x-y) which equals to (a+b)*(a-b) or 2*( x-y)
  • Lazy evaluation of function parameters (see the IF function) and support of sub-expressions.
  • Requires minimum Java version 11.

Documentation

The full documentation for EvalEx can be found on GitHub Pages

Discussion

For announcements, questions and ideas visit the Discussions area.

Download / Including

You can download the binaries, source code and JavaDoc jars from Maven Central.
You will find there also copy/paste templates for including EvalEx in your project with build systems like Maven or Gradle.

Maven

To include it in your Maven project, add the dependency to your pom. For example:

<dependencies>
    <dependency>
      <groupId>com.ezylang</groupId>
      <artifactId>EvalEx</artifactId>
      <version>3.2.0</version>
    </dependency>
</dependencies>

Gradle

If you're using gradle add the dependencies to your project's app build.gradle:

dependencies {
    compile 'com.ezylang:EvalEx:3.2.0'
}

Examples

A simple example, that shows how it works in general:

Expression expression = new Expression("1 + 2 / (4 * SQRT(4))");

EvaluationValue result = expression.evaluate();

System.out.println(result.getNumberValue()); // prints 1.25

Variables can be specified in the expression and their values can be passed for evaluation:

Expression expression = new Expression("(a + b) * (a - b)");

EvaluationValue result = expression
    .with("a", 3.5)
    .and("b", 2.5)
    .evaluate();

System.out.println(result.getNumberValue()); // prints 6.00

Expression can be copied and evaluated with a different set of values:

Using a copy of the expression allows a thread-safe evaluation of that copy, without parsing the expression again. The copy uses the same expression string, configuration and syntax tree. The existing expression will be parsed to populate the syntax tree.

Make sure each thread has its own copy of the original expression.

Expression expression = new Expression("a + b").with("a", 1).and("b", 2);
Expression copiedExpression = expression.copy().with("a", 3).and("b", 4);

EvaluationValue result = expression.evaluate();
EvaluationValue copiedResult = copiedExpression.evaluate();

System.out.println(result.getNumberValue()); // prints 3
System.out.println(copiedResult.getNumberValue()); // prints 7

Values can be passed in a map

Instead of specifying the variable values one by one, they can be set by defining a map with names and values and then passing it to the withValues() method:

The data conversion of the passed values will automatically be performed through a customizable converter.

It is also possible to configure a custom data accessor to read and write values.

Expression expression = new Expression("a+b+c");

Map<String, Object> values = new HashMap<>();
values.put("a", true);
values.put("b", " : ");
values.put("c", 24.7);

EvaluationValue result = expression.withValues(values).evaluate();

System.out.println(result.getStringValue()); // prints "true : 24.7"

See chapter Data Types for details on the conversion.

Another option to have EvalEx use your data is to define a custom data accessor.

See chapter Data Access for details.

Boolean expressions produce a boolean result:

Expression expression = new Expression("level > 2 || level <= 0");

EvaluationValue result = expression
    .with("level", 3.5)
    .evaluate();

System.out.println(result.getBooleanValue()); // prints true

Like in Java, strings and text can be mixed:

Expression expression = new Expression("\"Hello \" + name + \", you are \" + age")
    .with("name","Frank")
    .and("age",38);

System.out.println(expression.evaluate().getStringValue()); // prints Hello Frank, you are 38

Arrays (also multidimensional) are supported and can be passed as Java Lists or instances of Java arrays.

See the Documentation for more details.

Expression expression = new Expression("values[i-1] * factors[i-1]");

EvaluationValue result = expression
    .with("values", List.of(2, 3, 4))
    .and("factors", new Object[] {2, 4, 6})
    .and("i", 1)
    .evaluate();

System.out.println(result.getNumberValue()); // prints 4

Structures are supported and can be passed as Java Maps.

Arrays and Structures can be combined to build arbitrary data structures. See the Documentation for more details.

Map<String, Object> order = new HashMap<>();
order.put("id", 12345);
order.put("name", "Mary");

Map<String, Object> position = new HashMap<>();
position.put("article", 3114);
position.put("amount", 3);
position.put("price", new BigDecimal("14.95"));

order.put("positions", List.of(position));

Expression expression = new Expression("order.positions[x].amount * order.positions[x].price")
    .with("order", order)
    .and("x", 0);

BigDecimal result = expression.evaluate().getNumberValue();

System.out.println(result); // prints 44.85

Calculating with date-time and duration

Date-tme and duration values are supported. There are functions to create, parse and format these values. Additionally, the plus and minus operators can be used to e.g. add or subtract durations, or to calculate the difference between two dates:

Instant start = Instant.parse("2023-12-05T11:20:00.00Z");
Instant end = Instant.parse("2023-12-04T23:15:30.00Z");

Expression expression = new Expression("start - end");
EvaluationValue result = expression
        .with("start", start)
        .and("end", end)
        .evaluate();
System.out.println(result); // will print "EvaluationValue(value=PT12H4M30S, dataType=DURATION)"

See the Documentation for more details.

EvalEx-big-math

Big-math is a library by Eric Obermühlner. It provides advanced Java BigDecimal math functions using an arbitrary precision.

EvalEx-big-math adds the advanced math functions from big-math to EvalEx.

Author and License

Copyright 2012-2023 by Udo Klimaschewski

Thanks to all who contributed to this project: Contributors

The software is licensed under the Apache License, Version 2.0 ( see LICENSE file).

evalex's People

Contributors

codingeass avatar dependabot[bot] avatar evanpratama avatar gangeli avatar hsgamer avatar humazed avatar karlivory avatar luis451 avatar luiz-resende avatar mdzhb avatar michelkaeser avatar nico72 avatar numberc avatar oswaldobapvicjr avatar prajwalbanakar26 avatar qwert2003 avatar rbuehlma avatar revbingo avatar rjcohn avatar robertzenz avatar sboyina avatar snownee avatar squeek502 avatar ssheikin avatar stevenylai avatar sxtanna avatar ugurk avatar uklimaschewski avatar wangxu0 avatar xlukasbx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

evalex's Issues

Mutability of Expression makes it non ideal for using the cached instance

public class Equation {

    private String expressionString;
    private Expression expression;

    public Equation(String expressionString) {
        hasLength(expressionString, "Invalid Expression %s specified");
        this.expressionString = expressionString;
        expression = new Expression(expressionString);
    }
}

the above equation instance has expression string and constructs Expression once and caches the equation, but since the Expression mutates the internal map, it becomes very cumbersome to evaluate the expression as the below

(-327865.5593 + Yearly * 7699.1161 + FQ1 * 118965.3548 + FQ2 * -19003.9418 -38640 + FQ3 * 75560 + FQ4 * -21700)/1000000

where we can expect only one fQ per execution, and while doing batch execution, the evaluation can quickly get cumbersome,

what I basically want to do is

public List<BigDecimal> eval(Map<TimeLineInQuarter.Quarters, Double> variables, Yearly y) {
              Arrays.stream(TimeLineInQuarter.Quarters.values()).forEach(
                Errors.rethrow().wrap(q -> {
                            expression.with("Yearly", new BigDecimal(y.quarterly(q)))
                                    .with(q.name(), new BigDecimal(variables.get(q)));
                        }
                )
        );

      //not intended to compile, Idea is I will be able to execute the equation for every quarter for a given year
        return collectedvalue;

    }

Making the Expression immutable, I would be able to use the same Expression multiple times, but in the above case, I will end up constructing one expression per execution, though it may appear to be specific to my equation, I would stress that Immutable Expression would be ideal as construction of Expression as I see is costly

slow string replace

here you use String.replace with regex.

First question is: is the regex really necessary? I couldn't face a case where it was necessary.
Maybe be you could make it an option? I use your lib for realtime computation and so every little improvement is a big improvement ;)

Now if you decided to go to a simple replace like i did then you would face the problem that String.replace always uses regex and is really slow.

For reference you can use a faster replace like this:

public static String fastReplace(String source, String os, String ns) {
        if (source == null) {
            return null;
        }
        int i = 0;
        if ((i = source.indexOf(os, i)) >= 0) {
            char[] sourceArray = source.toCharArray();
            char[] nsArray = ns.toCharArray();
            int oLength = os.length();
            StringBuilder buf = new StringBuilder(sourceArray.length);
            buf.append(sourceArray, 0, i).append(nsArray);
            i += oLength;
            int j = i;
            // Replace all remaining instances of oldString with newString.
            while ((i = source.indexOf(os, i)) > 0) {
                buf.append(sourceArray, j, i - j).append(nsArray);
                i += oLength;
                j = i;
            }
            buf.append(sourceArray, j, sourceArray.length - j);
            source = buf.toString();
            buf.setLength(0);
        }
        return source;
    }

Evaluation performance for large numbers

Hey Udo, first of all thanks for the awesome library!

I'm using the EvalEx library for the Liferay portal project but we've found something that impacts the performance of some operations.

For example expression such as SQRT(9123744984893^993837) takes a lot of time to evaluate and the eval() method hangs for a while.

We can solve this at our side, but I was wondering if that's something you would like to include in your library. Something like a timed out condition for evaluations. I can send you a pull request if you think so.

Let me know what you think.

Best Regards @uklimaschewski,

Support of nested expressions?

I've looked at the code quickly and tried to figure out a quick way to patch it to support nested expressions, but have been unable to do it easily.

I'm looking to support the following use case:

var1 = 10;
var2 = "5 * var1";
var3 = "25 + var2";

Expression e = new Expression( var3 ).with( "var2", var2).with( "var1", var1);
e.eval();

Is this functionality easily accomplished/added?

Default precision and scale

Hello, I found EvalEx is very useful and I have similar needs of BigDecimal in expression evaluator.
I really appreciate your great work.

Anyway, I found several issues when I tried to use it.

The first one is that Expression seems have an unclear default precision.
I just use this code to test:

Expression exp = new Expression(str);
System.out.println(exp.eval());

The input and output will be:
1.1234895 => 1.12349
1.1234891 => 1.123489

What I expected is:
1.1234895 => 1.1234895
1.1234891 => 1.1234891

I can get what I expected by adding:

exp.setPrecision(0);

It can solve this problem but I just get confused by the default behavior.
Can exp.setPrecision(0); be a default condition?

Another issue is that I could not control the scale during calculation.
We can control precision by setPrecision and ROUND(expression,precision) but there is no function for scale.

How do you think about these?
I'll dig into the code and try to contribute if I have time.

It is very nice of you if you could do some improvement.

Thank you very much!

Maven Release?

Hi Udo,

This project looks great, thanks for your effort! We'd like to use EvalEx in one of our projects but see it hasn't been released to Maven central. Would you be able to release this?

The only alternative for us would be to download the source, build it, upload it to our own repository and work off of that. But that sort of defeats the dependency management feature of Maven and we'd opt to use a different tool.

I'd be happy to help you release this if you're new to the process.

Best,
Sean

other function use

hello;

my function

public int test(int a, int b, int c) {
return a+b+c;;
}

can i use

Expression e = new Expression("2 * test(12,4,8)");

        e.addFunction(e.new Function("test", -1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                if (parameters.size() == 0) {
                    throw new Expression.ExpressionException("average requires at least one parameter");
                }
                BigDecimal avg = new BigDecimal(0);
                for (BigDecimal parameter : parameters) {
                    avg = avg.add(parameter);
                }
                return avg.divide(new BigDecimal(parameters.size()));
            }
        });

        e.eval(); 

thank you, and thank you google translate :)

Bug

Hallo Udo,

die if() Formel hat einen kleinen Bug.
Wenn man if (true, -x+y,0) auswerten, möchte, dann kommt es zu einer Fehlermeldung.

Scientific Notation Support

Hello, I have been trying to use the lib for large numbers and the result is shown in scientific notation, which is great. Anyway there's an issue when I try to use that result for a new expression, lets say:
2.551633e11*5

I get an exception:
java.lang.RuntimeException: Unknown operator or function: e11

And I've checked through the github repository and I've found some unit tests for scientific notation, but I couldnt find this in the lib. Is this supported in future versions and not in 1.0?

Thanks in advance.

Functions use.

hi;

//my functions;

public Double FICLC(String item, Integer param){
return 1d;
}
public Double FGCLC(String item, String itemtwo, Integer param){
return 1d;
}
public Double FYCLC(String item){
return 1d;
}

new Expression("(FICLC("012844098501",1)>=1) && (FGCLC("A11","ABC",1)>1) && (FYCLC("A11")=1) ");

I have to watch how a road ?

Thank you.

support for decimals without leading zeros

in Expression.java, line 595, I had to change the line to:

if (Character.isDigit(ch) || (ch == decimalSeparator && Character.isDigit(peekNextChar()))) {

in order to account for .5 instead of 0.5

Quick Question about BigDecimal and If function

The project I am using EvalEx on is money based therefore all calculation falls in the limits of double. BigDecimal arithmetic function is known to be much more slower than primitive like double. I am exploring the possibility of wrapping the Values EvalEX in a pseudo class that supports BigDecimal as well as primitives like double or even floats in extreme case. For use cases that are can tolerate precision losses based on performance gain.

This is going to dramatically change the code so i am asking to see if you will be willing to accept such a pull request.

If i go ahead with this modification. I would like to improve the if function as well. Consider the following
if(a =0, 0 , 12/a)
The above does not work well because 12/a is evaluated regardless of the outcome of a=0. This was a problem i ran into. I solved it by returning 0 for any divisible by 0 in my specific context. This is not ideal. I would like to lazily evaluate the parameters of the if based on the outcome of the boolean tester.

use String parameters in custom functions

Hi dear
I want to evaluate a function like this: myFunction(23A12B,H341B1), but the parser didn't recongize the whole 23A12B as a parameter!
how do i can do this?

Make Function and Operator static

If made static, I wouldn't need to create a Function dependent of the variable, the same way you do inside Expression class.

There should be no other changes to the code Also, I could use it in Kotlin ;D

Problem with sqrt

Hello Udo,
Thank you producing such a useful library.
I came across an issue where sqrt function is getting stuck in this loop.
do {
ixPrev = ix;
ix = ix.add(n.divide(ix)).shiftRight(1);
// Give other threads a chance to work;
Thread.yield();
} while (ix.compareTo(ixPrev) != 0);

I ended up overriding the function with java's sqrtj implementation.

ASIN, ACOS and ATAN

Also, I think it is a good idea to add this line to all trigo functions:

if (d == 0) return BigDecimal.ZERO;

minus "-" doesn't work before Open Parentheses "("

first, you did a great job. your EvalEx is awsome. but there is one annoying thing. - doesn't work before (. below expressions are really common and used alot, but evalex can't handle it. and throws exception.
(-(5))
(-(5+3)+3)
that would be great if it could handle above expressions.

Problem with brackets

There are two issue that i found and i dont know how to fix it. Issue is if you have string like this "2_3(5_3)", the answer should be 90 but the program gives 45. Any suggest about how shall i fix this??

Also expression like "2_3_(5*3)" should give answer 90 but instead it gives 9E+1.

How i can turn off the scientific notation for results?

Hi, first i have to say my congratulations for your project, very god job man. I am mading a simple calculator (my first Android app), and i have issues with the notation of results:
For example, if i do "10+10" instead of give me "20" as result it give me "2E+1".

You know how i cant fix it?

PD: sorry for my bad english

Support for more trigonometric functions

currently it supports Sin, Cos, Tan. hyperbolic and also arc.
it would be nice if it could answer below functions:
Sec, Csc
Sech, Csch
Cot, aCot, Coth
aSinh, aCosh, aTanh

IF evaluation

Hi,

why does IF(TRUE,1,1/0) throw a division by zero error ? Seems like 1/0 is evaluated regardless of
the result of the if condition ?

thanks!
gerald

Default precision is 7 instead of 13 ?

I found out that the precision of BigDecimal result from Expression.eval() is 7 instead of 13 which is default in BigDecimal:

   BigDecimal bd = new BigDecimal("1442503274032");
   System.out.println(bd.precision());    // print 13

   Expression expr = new Expression("1442503274032");
   BigDecimal res = expr.eval();
   System.out.println(res.precision());    // print 7

Is there a reason why use 7 instead of 13 ?
I know the precision can be set but I prefer if it conforms to the default.

Scientific notation

Scientific notation ("2.2E-16") within expressions currently is not supported.

Example (calling EvalEx from BeanShell) ...

addClassPath("drawj2d.jar"); // BeanShell (bsh2) syntax
import com.udojava.evalex.*;
import java.math.BigDecimal;

String expr2 = "2.2E-16 * 10.2";
Expression expression = new Expression(expr2);
BigDecimal result = expression.eval();

... fails throwing an exception:

java.lang.RuntimeException: Unknown operator or function: E
        at com.udojava.evalex.Expression.shuntingYard(Expression.java:1149)
        at com.udojava.evalex.Expression.getRPN(Expression.java:1353)
        at com.udojava.evalex.Expression.eval(Expression.java:1166)

I once asked in the comments section of Udo's blog. The answer was:

Scientific notation, this could get tricky. But I guess it is possible to implement in the tokenizer.

The java method call new BigDecimal("2.2E-16") does parse numbers in scientific notation. So it seems that it would be enough to tell the EvalEx tokenizer to understand the number in scientific notation as a single statement.
Trying ...

Index: com/udojava/evalex/Expression.java
===================================================================
--- com/udojava/evalex/Expression.java  (revision 263)
+++ com/udojava/evalex/Expression.java  (working copy)
@@ -593,7 +593,8 @@
                                ch = input.charAt(++pos);
                        }
                        if (Character.isDigit(ch)) {
-                               while ((Character.isDigit(ch) || ch == decimalSeparator)
+                               while ((Character.isDigit(ch) || ch == decimalSeparator
+                                                || ch == 'e' || ch == 'E')
                                                && (pos < input.length())) {
                                        token.append(input.charAt(pos++));
                                        ch = pos == input.length() ? 0 : input.charAt(pos);
@@ -1056,7 +1057,8 @@
                        return false;
                for (char ch : st.toCharArray()) {
                        if (!Character.isDigit(ch) && ch != minusSign
-                                       && ch != decimalSeparator)
+                                       && ch != decimalSeparator
+                                        && ch != 'e' && ch != 'E')
                                return false;
                }
                return true;
@@ -1398,6 +1400,7 @@
                        }
                        counter++;
                }
+                System.err.println("DEBUG: " + rpn.toString());
                if (counter > 1) {
                        throw new ExpressionException("Too many numbers or variables");
                } else if (counter < 1) {

... works for expressions like "2.2E16 * 10.2" but still fails for "2.2E-16".

Any idea how EvalEx can be told to recognize "2.2E-16" as a single number?

setRoundingScale?

Hallo,

ich habe ein Problem mit MathContext der Expression-Klasse:
Die Precision des MathContext bezieht sich auf alle Ziffern inklusive der Vorkommastellen, sodass meine Ergebnisse gegebenenfalls sehr ungenau werden (bei MathContext.DECIMAL32):
Könnte man vielleicht statt der Precision einen Scale setzen, sodass diese sich nur auf die Nachkommestellen beziehen? (setPrecision vs setScale?)

Ich glaube ich habe noch nicht verstanden, warum überhaupt mit einem MathContext gearbeitet wird (anstelle eines Scales mit RoundingMode), können Sie mir da weiterhelfen?

support variable names starting with '_'

It would be nice for EvalEx to support variable names starting with '_'

I tested it simply by changing that line with this:

            } else if (Character.isLetter(ch) || (ch == '_')) {

I also changed that line to this:

                while (!Character.isLetter(ch) && !Character.isDigit(ch) && ch != '_'

dynamic precision

Hay Udo. Thank you very much for this amazing repository. This is exactly what I was looking for.

This is not a bug report, but rather a personal problem I ran into. Would be great if you could maybe help me out.

I am trying to get the right precision for every occasion:

  1. A normal decimal number should have a a precision of 5
    (1/3 = 1.33333)
  2. A calculation with decimal numbers should orient on the largest decimal point and set the precision according to it:
    (0.1234567 + 0.1234 = 0.2468567)
  3. Big numbers should have the maximum precision:
    (12345678 * 123456 = 1524148023168)

I have tried several things like setting the precision to 128, which gives me (3) and (2) but (1) spammed the output with too many periodic "3"s.

Could you maybe hint me in the right direction?

Thanks again for the amazing code
Liebe Grüsse Haeri

Max function for more than 2 arguments

max(3.0, 2.0, 1.0) returns 2.0. The expected answer would be 3.0.
min(1.0, 2.0, 3.0) returns 2.0. The expected answer would be 1.0.

Currently max expects two arguments. If more arguments are passed to the function, the last two are taken (no error). This is not obvious.

Could max (and min) be extended to accept any number of arguments (>1)?

Feature Request: NULL als Konstante

Hallo Herr Klimaschewski,
könnten Sie mir helfen,
evalEx so zu erweitern, dass man eine Konstante mit null hat.

Brauchen tue ich z.B. für eine IF-ELSE-Formel:

    @Test
    public void testNullAsConstant()
    {
        String formel = "if(y==0, NULL, x/y)";
        Expression e = new Expression(formel);
        e.with("y", BigDecimal.ZERO);
        e.with("x", BigDecimal.TEN);
        e.with("NULL", (BigDecimal) null);

        // ------ VERIFY ------- //
        assertNull(e.eval());
    }

ich dachte man könnte mit Hinzufügen einer neuen "Variable" das Problem lösen:
m_variables.put("NULL", null);

Aber da bekomme ich auch ein NPE.

Vielen Dank im Voraus.

Support for implicit multiplication

Hello,
are there any plans to support implicit multiplications, so that 5SIN(2) will be interpreted as 5*SIN(2)? (Or is this even already possible and I am just unable to find this functionality?)

Edit: I tried to solve this issue by modifing the shuntingYard method by adding addition if-statements like this

if (isNumber(token)) {
      if (previousToken != null && ")".equals(previousToken))
      {
           stack.push("×");
      }
     ...
} else if (functions.containsKey(token.toUpperCase(Locale.ROOT))) {
     if (previousToken != null && isNumber(previousToken))
     {
            stack.push("×");
     }
 ....

This seems to work after a few test, but I am not completely sure about it. Are there any opinions?

BigDecimal Rounding problem

Here is my code

public class test {
public static void main(String args[])
{
String str="(1/3)*3";
Expression exp = new Expression(str);
System.out.println("ans: "+exp.eval().toPlainString());
}
}

The output should be 1 but i am getting something lke this ans: 0.9999999.

I read on internet that toPlainString() removes such problem but it is not working in my case. Can you suggest me what to do.

Sorry to disturb you again

Best way to retrieve variables from Expressions?

Hi Udo,

is there any convinient way to retrieve all variables which are used within an Expression? Something like that?
Expression exp = new Expression("$variableA - $variableB * 10)
exp.getVariables(); // returns variableA and variableB in List<String>

IF-Expression (both cases are executed)

Hello Udo,
thanks for your project.
I have a problem with the IF-Expression. If a condition evaluates to false both expressions are executed.

example:
value1 = 0;
value2 = 2;
IF(value1>0,value2/value1,0)

value2/value1 (2/0) will be executed.
In this case Java throws an "ArithmeticException: Division by zero".

request:
First the condition should be tested and then one of the two values should be excuted.

Can you fix that problem?

I am looking forward to hearing from you.

Best regards,
Kai

Combine IF ?

Hi, I'm looking to use your lib but I have a question: can we combine IF statement like

IF(cond1,IF(cond2,true,false),IF(cond3,true,false))

Thanx

factorial operator

insert the following in the operators list:

    ///////////////////////////////////////////////////
    addOperator(new Operator("!", 50, true)
    {
        BigDecimal fac(BigDecimal n, BigDecimal acc)
        {
            if (n.equals(BigDecimal.ONE))
            {
                return acc;
            }
            BigDecimal lessOne = n.subtract(BigDecimal.ONE);
            return fac(lessOne, acc.multiply(lessOne, mc));
        }

        @Override
        public BigDecimal eval (BigDecimal v1, BigDecimal v2)
        {
            return fac (v1, v1);
        }
    });
    ///////////////////////////////////////////////////

... then replace every ! in the input string with !0 to fake a second op
now one can calculate
3!^4 = 1296
3! = 6
8! = 40320
and so on ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.