With Jep 3 and later, it is possible to evaluate expressions using decimal arithmetic. This allows calculations to be performed with specified accuracy or even unlimited accuracy. If you are running into precision problems or already know that you will require the highest possible precision in your calculations, we recommend using this operation mode.
Rather than using the double
type to represent numbers, BigDecimal
is used. The BigDecimal
class is part of the Java API and is
contained in the java.math
package. For more information on this
class, please read the
BigDecimal documentation.
The difference in the accuracy is best shown through an example. When performing
multiplication of two numbers of the double
type,
10*0.09 evaluates as 0.8999999999999999.
But when performing the same calculation using decimal arithmetic with the
BigDecimal
type,
10*0.09 evaluates as 0.9.
Note, care is needed when using BigDecimls as
10.0*0.09 evaluates as 0.90.
a subtly different BigDecimal value.
Using Jep in BigDecimal mode is simple. Simply create a new Jep instance using the BigDecComponents with:
import com.singularsys.jep.bigDecimals.BigDecComponents; ... jep = new Jep(new BigDecComponents());
This initializes Jep with a special the BigDecNumberFactory, BigDecOperatorTable and BigDecFunctionTable. By default, the math context is set to unlimited precision. But you can also initialize the components with a different math context. For example, to use 32-bit precision numbers simply use
jep = new Jep(new BigDecComponents(MathContext.DECIMAL32));
For more information about MathContexts refer to the Sun MathContext Javadocs.
Guaranteeing precision unfortunately comes at the cost of more complex algorithms
for basic operators and functions. For this reason, some of the functions
and operators available for double
arithmetic are not available
in the BigDecimal mode.
The supported operators and functions are below. These are all available by default with the BigDecComponents.
+, -, *, /, ^ (power), % (modulus)
>, <, >=, <=, == (equals)
&& (and), || (or), ! (not)
Functions | Description | Class |
---|---|---|
round(val) ,round(val,dp) |
Round numbers. Two argument version round to a specific number of decimal places. | BigDecRound |
rint(val) rint(val,dp) |
Round numbers, with the round half even rounding mode. | BigDecRound |
ceil(val) floor(val) |
Floor and ceiling functions. | BigDecRound |
roundSF(val,sf) |
Round numbers to a specified number of significant figures. | BigDecRoundSigFig |
abs(val) |
Absolute value function. | BigDecAbs |
signum(val) |
Sign of the argument either -1, 0 or 1. | BigDecSignum |
if(cond, true_val, false_val) |
If function. | If |
min(val1,val2,...) max(val1,val2,...)
|
Min and Max functions. | BigDecTieBreakComparative, MinMax |
avg(val1,val2,...)
|
Average | Average |
Just like with Jep in standard mode, you can add your own custom functions.
By default BigDecimal and Strings cannot be used together but as of release 3.4 this can now be turned on. The following code switches on this facility and adds the standard string functions.
// Create the BigDecComponents BigDecComponents compSet = new BigDecComponents(MathContext.DECIMAL64,true); // Create a jep instance jep = new Jep(compSet); // Add the standard set of string functions jep.setComponent(new StringFunctionSet());
The above code will allow strings to be concatenated using '+' and compared using '==', '!=', '<', '<=', '>=', '>'. The StringFunctionSet allows the left, right, lower, upper, substring, len, mid, trim.