Jexl arithmetic calculations are not accurate

45 views Asked by At

I have an application that receives a list of JEXL expressions and evaluates them in the loop with data retrieved from the database. It does work, but calculations are not accurate. For example, this simple formula:

a*b+c

where a is integer, b - float and c - double. with values a = 600, b = 6.287 and c = 102.245 result is suppose to be 3874.445 but JEXL gives me 3874.223. I checked it on couple hundreds of samples and error varies from 0.001% to 0.3% but I never got exact answer. My JEXL engine looks like this:

JexlEngine jexl = new JexlBuilder().cache(2048).silent(false).strict(false).create();

I did put strict to false, because some data might be null and I don't want JEXL to barf on such data. Any ideas why it is happening?

1

There are 1 answers

4
henrib On BEST ANSWER

The short answer is look at IEEE 754 double-precision binary floating-point format. This implies that, even in pure Java code, you get a result like:

double r = 600 * 6.287f + 102.245d; // r == 3874.4451953125

A longer answer is that you can derive JexlArithmetic so that every operator converts its arguments to BigDecimal to obtain a precise answer. As an example, the following evaluates 'correctly' (note the 600b which makes the first number a BigDecimal).

  @Test
  public void testSO20230225() throws Exception {
    String src = "let a = 600b; let b = 6.287f; let c = 102.245d; a * b + c";
    final JexlBuilder builder = new JexlBuilder();
    final JexlEngine jexl = builder.create();
    JexlScript script = jexl.createScript(src);
    Object result = script.execute(null);
    double r = 3874.445d;
    Assert.assertEquals(r, ((Number) result).doubleValue(), 0.0000001d);
  }