Оцените расчет с помощью интерпретатора, но значение слишком велико

Я использую интерпретатор BeanShell в Java для решения строковых вычислений. проблема в том, что я сам выполняю некоторый синтаксический анализ, который не может быть выполнен интерпретатором, и сохраняю частичный результат в BigInteger. Затем я собираю все вместе и даю интерпретатору решить, но числа, которые я получаю с BigInteger.toPlainString(), слишком велики для interpreter.eval(...), потому что я получаю следующее сообщение об ошибке:

 Parse error at line 1, column 10 : Error or number too big for integer type: 2432902008176640000
    Parse error at line 1, column 10 : Error or number too big for integer type: 2432902008176640000

Строка расчета строится следующим образом:

    BigDecimal x = new BigDecimal(/*very big number*/);
    BigDecimal y = new BigDecimal(/*very big number*/);
    String s = x.toPlainString() + "+" + y.toPlainString();

    Interpreter i = new Interpreter();
    i.eval("result = " + s);
    s = i.get("result").toString();

Я знаю, что в этом случае я мог бы просто сложить числа с помощью предоставленной функции BigDecimal, но в моем случае расчет намного сложнее! Есть ли возможный обходной путь, чтобы я мог использовать оценщик beanshell и с огромными числами?


person wasp256    schedule 05.09.2013    source источник


Ответы (1)


Я предполагаю, что ваш сценарий действительно более сложный, поэтому вы не можете просто сделать это без BeanShell:

s = x.add(y).toString();

Если это так, вы должны знать, что вы можете получить доступ к объектам BigDecimal непосредственно из вашего выражения:

i.set("x", x);
i.set("y", y);
i.eval("result = x.add(y);");
s = i.get("result").toString();

Вы даже можете сделать:

String someBigNumber1, someBigNumber2;
// Set the number strings
i.set("xStr", someBigNumber1);
i.set("yStr", someBigNumber2);
i.eval("import java.math.BigDecimal;");
i.eval("result = new BigDecimal(xStr).add(new BigDecimal(yStr));");
s = i.get("result").toString();

BeanShell использует синтаксический анализ и отражение AST «на лету» для интерпретации инструкций и разрешения методов на основе конкретных типов 1) вещей, передаваемых в него, и 2) вещей, возвращаемых методами. Это очень похоже на то, как различные языки сценариев имеют var переменных, которые явно не типизированы. Например, поскольку BeanShell использует интерпретатор и разрешает типы во время выполнения, а не во время компиляции (которого в BeanShell нет, за исключением создания AST, который занимается синтаксическим анализом, а не компиляцией), это допустимо в BeanShell:

i.set("xStr", someBigNumber1);
i.set("yStr", someBigNumber2);
i.eval("import java.math.BigDecimal;");
i.eval("x = new BigDecimal(xStr);");
i.eval("y = new BigDecimal(yStr);");
i.eval("result = x.add(y);");
s = i.get("result").toString();

Несмотря на то, что я не объявлял x и y как BigDecimal, я все еще могу вызвать add на x и передать y. Это связано с тем, что когда BeanShell запускает код, он знает конкретные типы x и y и разрешает метод на лету, используя отражение.

person Brian    schedule 11.09.2013
comment
Я копирую/вставляю ваш код выше, но получаю сообщение об ошибке Sourced file: inline evaluation of: ``x = new BigDecimal(xStr);y = new BigDecimal(yStr);result = x.add(y);'' : Unknown class: BigDecimal Sourced file: inline evaluation of: ``x = new BigDecimal(xStr);y = new BigDecimal(yStr);result = x.add(y);'' : Unknown class: BigDecimal : at Line: 1 : in file: inline evaluation of: ``x = new BigDecimal(xStr);y = new BigDecimal at bsh.BSHAllocationExpression.objectAllocation(Unknown Source) - person wasp256; 13.09.2013
comment
@wasp256 wasp256 Извините, забыл import утверждения. Вы также можете напрямую ссылаться на BigDecimal, т.е. new java.math.BigDecimal(xStr); - person Brian; 13.09.2013