javacalculationjexl

Jexl arithmetic calculations are not accurate


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?


Solution

  • 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);
      }