Variable Math
In MAPPER, operators like +, -, and * perform math on variables in commands like @ART,
@CHG and @CAL. The
MJ variable classes support similar mathematical operations and functions via
the IMathOperators
and IMathFunctions interfaces.
Only MJDecimal,
MJInteger and MJVariant implement
these interfaces; while MJ
supports math involving MJString variables,
it follows Java's strong typing by encouraging math on numbers and discouraging math on strings.
MJ also provides formulas as a convenient way to perform math with variables;
internally, formulas make use of the IMathOperators and
IMathFunctions interfaces.
Interface IMathOperators
Here are the binary and unary mathematical methods available in IMathOperators:
| MAPPER Operator | Description | IMathOperators Method |
|---|---|---|
| + | Addition: a+b |
add |
| - | Subtraction: a-b |
subtract |
| / | Division: a/b |
divide |
| // | Integer division: a//b. Gives the unrounded integer portion of the dividend of
value a divided by value b. |
divideToIntegralValue |
| * | Multiplication: a*b |
multiply |
| ** | Exponentiation: a**b. Gives the result of value a raised
to the power of value b. |
pow |
| - | Unary minus: -a. Gives the negative of value a. |
negate |
The IMathOperators interface also
supports increment and
decrement as the equivalent of MAPPER
@INC and @DEC.
Interface IMathFunctions
The mathematical functions supported
by @ART and @CAL are
available in IMathFunctions:
| MAPPER Function | Description | IMathFunctions Method |
|---|---|---|
ABS(x) |
Absolute value or magnitude of x. |
abs |
MOD(x,y) |
Modulus; remainder value of x/y. |
mod |
FRAC(x) |
Fractional portion of x. |
frac |
INT(x) |
Integer portion of x. |
intf |
SQRT(x) |
Square root of x. |
sqrt |
Methods similar to trigonometric functions like ACOS(x),
DEG(x) and
LOG(x) are also
present in IMathFunctions.
Examples of Math with MJ Numeric Variables
Here are examples of mathematical methods and functions supported by MJDecimal
and MJInteger:
//////////////////// Addition (@CHG) ////////////////////////////////////
// @LDV <decVar>f3.2=9.428 .
// @CHG <sumVar>f7.3 <decVar> + 22 .
MJDecimal decVar = new MJDecimal(VariableScope.LOCAL, 3, 2, new BigDecimal("9.428"));
Number sum = decVar.add(22L, EnumSet.of(MathOption.EVALUATE_JAVA_TYPE));
assert sum instanceof BigDecimal;
MJDecimal sumVar = new MJDecimal(VariableScope.LOCAL, 7, 3, (BigDecimal) sum);
assert "31.428".equals(sumVar.toMapperNumericString());
//////////////////// Subtraction (@ART) /////////////////////////////////
// @LDV <sub1>f4.2=10.8765, <sub2>f4.2=-1.43 .
// @ART <sub1>-<sub2> <diffVar>f18.17 .
MJDecimal sub1 = new MJDecimal(VariableScope.LOCAL, 4, 2, new BigDecimal("10.8765"));
MJDecimal sub2 = new MJDecimal(VariableScope.LOCAL, 4, 2, new BigDecimal("-1.43"));
Number diff = sub1.subtract(sub2, EnumSet.of(MathOption.EVALUATE_MAPPER_TYPE));
assert diff instanceof BigDecimal;
MJDecimal diffVar = new MJDecimal(VariableScope.LOCAL, 18, 17, (BigDecimal) diff);
assert "12.300000000000000".equals(diffVar.toMapperNumericString());
//////////////////// Multiplication (@CHG) //////////////////////////////
// @LDV <mpc>i9=987654321, <mpi>i8=86453095 .
// @CHG <intRslt>i16 <mpc> * <mpi> .
MJInteger mpc = new MJInteger(VariableScope.LOCAL, 9,
EnumSet.noneOf(LoadOption.class), "987654321");
MJInteger mpi = new MJInteger(VariableScope.LOCAL, 8,
EnumSet.noneOf(LoadOption.class), "86453095");
Number prod = mpc.multiply(mpi, EnumSet.of(MathOption.EVALUATE_JAVA_TYPE));
assert prod instanceof Long;
MJInteger intRslt = new MJInteger(VariableScope.LOCAL, 16, ((Long) prod).longValue());
assert "8.53857728406E16".equals(intRslt.toMapperNumericString());
//////////////////// Division (@CHG) ////////////////////////////////////
// @LDV <dvd>i4=22, <dvi>i4=7 .
// @CHG <fltPi>f18.17 <dvd> / <dvi> .
MJInteger dvd = new MJInteger(VariableScope.LOCAL, 4,
EnumSet.noneOf(LoadOption.class), "22");
MJInteger dvi = new MJInteger(VariableScope.LOCAL, 4,
EnumSet.noneOf(LoadOption.class), "7");
Number quot = dvd.divide(dvi, EnumSet.of(MathOption.EVALUATE_JAVA_TYPE,
MathOption.PREFER_DECIMAL_OVER_FLOAT));
assert quot instanceof BigDecimal;
MJDecimal fltPi = new MJDecimal(VariableScope.LOCAL, 18, 17, (BigDecimal) quot);
assert "3.1428571428571400".equals(fltPi.toMapperNumericString());
//////////////////// Integer Division (@CHG) ////////////////////////////
// @LDV <dvd>i4=22, <dvi>i4=7 .
// @CHG <fltPi>f18.17 <dvd> // <dvi> .
Number iq = dvd.divideToIntegralValue(dvi, EnumSet.of(MathOption.EVALUATE_JAVA_TYPE));
assert iq instanceof Long;
MJDecimal fltIQ = new MJDecimal(VariableScope.LOCAL, 18, 17,
BigDecimal.valueOf(((Long) iq).longValue(), 0));
assert "3.0000000000000000".equals(fltIQ.toMapperNumericString());
//////////////////// Exponentiation (@ART) //////////////////////////////
// @LDV <exp>i2=-2, <base>f3=-10.0 .
// @ART <base>**<exp> <fltPow>f18.17 .
MJDecimal base = new MJDecimal(VariableScope.LOCAL, 3, 0,
EnumSet.noneOf(LoadOption.class), "-10.0");
MJInteger exp = new MJInteger(VariableScope.LOCAL, 2,
EnumSet.noneOf(LoadOption.class), "-2");
Number power = base.pow(exp, EnumSet.of(MathOption.EVALUATE_MAPPER_TYPE));
assert power instanceof BigDecimal;
MJDecimal fltPow = new MJDecimal(VariableScope.LOCAL, 18, 17, (BigDecimal) power);
assert "0.0100000000000000".equals(fltPow.toMapperNumericString());
//////////////////// FRAC function (@ART) ///////////////////////////////
// @LDV <fnum>f3.2=1.23 .
// @ART FRAC(<fnum>) <fracRslt>f12.4 .
MJDecimal fnum = new MJDecimal(VariableScope.LOCAL, 3, 2,
EnumSet.noneOf(LoadOption.class), "1.23");
Number frac = fnum.frac(EnumSet.of(MathOption.EVALUATE_MAPPER_TYPE,
MathOption.PREFER_DECIMAL_OVER_FLOAT));
assert frac instanceof BigDecimal;
MJDecimal fracRslt = new MJDecimal(VariableScope.LOCAL, 12, 4, (BigDecimal) frac);
assert "0.2000".equals(fracRslt.toMapperNumericString());
//////////////////// MOD function (@ART) ///////////////////////////////
// @LDV <mdvd>f6.4=-4.4857, <mdiv>i1=2 .
// @ART MOD(<mdvd>,<mdiv>) <modRslt>f4 .
MJDecimal mdvd = new MJDecimal(VariableScope.LOCAL, 6, 4,
EnumSet.noneOf(LoadOption.class), "-4.4857");
MJInteger mdiv = new MJInteger(VariableScope.LOCAL, 4,
EnumSet.noneOf(LoadOption.class), "2");
Number mod = mdvd.mod(mdiv, EnumSet.of(MathOption.EVALUATE_MAPPER_TYPE,
MathOption.PREFER_DECIMAL_OVER_FLOAT));
assert mod instanceof BigDecimal;
MJDecimal modRslt = new MJDecimal(VariableScope.LOCAL, 4, 0, (BigDecimal) mod);
assert "-0.5".equals(modRslt.toMapperNumericString());