Mathematical Operations and Numeric Manipulation
For those functions that support Decimal and Number (whole number) types, the return value type depends on the input types. If either the subject or argument are a Decimal then the result will be a Decimal. If both values are Numbers then the result will be a Number. This includes Divide. This is to preserve backwards compatibility and to not force rounding errors.
plus
Description: Adds a numeric value to the Subject. If either the argument or the
Subject cannot be coerced into a Number, returns null
. Does not provide
handling for overflow.
Subject Type: Number or Decimal
Arguments:
-
Operand : The value to add to the Subject
Return Type: Number or Decimal (depending on input types)
Examples: If the "fileSize" attribute has a value of 100, then the Expression
${fileSize:plus(1000)}
will return the value
1100
.
minus
Description: Subtracts a numeric value from the Subject. Does not provide handling for overflow.
Subject Type: Number or Decimal
Arguments:
-
Operand : The value to subtract from the Subject
Return Type: Number or Decimal (depending on input types)
Examples: If the "fileSize" attribute has a value of 100, then the Expression
${fileSize:minus(100)}
will return the value 0
.
multiply
Description: Multiplies a numeric value by the Subject and returns the product. Does not provide handling for overflow.
Subject Type: Number or Decimal
Arguments:
-
Operand : The value to multiple the Subject by
Return Type: Number or Decimal (depending on input types)
Examples: If the "fileSize" attribute has a value of 100, then the Expression
${fileSize:multiply(1024)}
will return the value
102400
.
divide
Description: Divides the Subject by a numeric value and returns the result.
Subject Type: Number or Decimal
Arguments:
-
Operand : The value to divide the Subject by
Return Type: Number or Decimal (depending on input types)
Examples: If the "fileSize" attribute has a value of 100, then the Expression
${fileSize:divide(12)}
will return the value 8
.
mod
Description: Performs a modular division of the Subject by the argument. That is, this function will divide the Subject by the value of the argument and return not the quotient but rather the remainder.
Subject Type: Number or Decimal
Arguments:
-
Operand : The value to divide the Subject by
Return Type: Number or Decimal (depending on input types)
Examples: If the "fileSize" attribute has a value of 100, then the Expression
${fileSize:mod(12)}
will return the value 4
.
toRadix
Description: Converts the Subject from a Base 10 number to a different Radix (or number base). An optional second argument can be used to indicate the minimum number of characters to be used. If the converted value has fewer than this number of characters, the number will be padded with leading zeroes. If a decimal is passed as the subject, it will first be converted to a whole number and then processed.
Subject Type: Number
Arguments:
-
Desired Base : A Number between 2 and 36 (inclusive)
-
Padding : Optional argument that specifies the minimum number of characters in the converted output
Return Type: String
Examples: If the "fileSize" attributes has a value of 1024, then the following Expressions will yield the following results:
Expression | Value |
---|---|
${fileSize:toRadix(10)} |
1024 |
${fileSize:toRadix(10,
1)} |
1024 |
${fileSize:toRadix(10,
8)} |
00001024 |
${fileSize:toRadix(16)} |
400 |
${fileSize:toRadix(16,
8)} |
00000400 |
${fileSize:toRadix(2)} |
10000000000 |
${fileSize:toRadix(2,
16)} |
0000010000000000 |
fromRadix
Description: Converts the Subject from a specified Radix (or number base) to a base ten whole number. The subject will converted as is, without interpretation, and all characters must be valid for the base being converted from. For example converting "0xFF" from hex will not work due to "x" being a invalid hex character. If a decimal is passed as the subject, it will first be converted to a whole number and then processed.
Subject Type: String
Arguments:
-
Subject Base : A Number between 2 and 36 (inclusive)
Return Type: Number
Examples: If the "fileSize" attributes has a value of 1234A, then the following Expressions will yield the following results:
Expression | Value |
---|---|
${fileSize:fromRadix(11)} |
17720 |
${fileSize:fromRadix(16)} |
74570 |
${fileSize:fromRadix(20)} |
177290 |
random
Description: Returns a random whole number ( 0 to 2^63 - 1) using an insecure random number generator.
Subject Type: No subject
Arguments: No arguments
Return Type: Number
Examples: ${random():mod(10):plus(1)}
returns random number
between 1 and 10 inclusive.
math
Description: ADVANCED FEATURE. This expression is designed to be used by advanced users only. It utilizes Java Reflection to run arbitrary java.lang.Math static methods. The exact API will depend on the version of Java you are running. The Java 8 API can be found here: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html
In order to run the correct method, the parameter types must be correct. The Expression Language "Number" (whole number) type is interpreted as a Java "long". The "Decimal" type is interpreted as a Java "double". Running the desired method may require calling "toNumber()" or "toDecimal()" in order to "cast" the value to the desired type. This also is important to remember when cascading "math()" calls since the return type depends on the method that was run.
Subject Type: Subjectless, Number or Decimal (depending on the desired method to run)
Arguments:
-
Method : The name of the Java Math method to run
-
Optional Argument : Optional argument that acts as the second parameter to the method.
Return Type: Number or Decimal (depending on method run)
Examples:
-
${math("random")} runs Math.random().
-
${literal(2):toDecimal:math("pow", 2.5)} runs Math.pow(2D,2.5D).
-
${literal(64):toDouble():math("cbrt"):toNumber():math("max", 5)} runs Math.maxDouble.valueOf(Math.cbrt(64D).longValue(), 5L). Note that the toDecimal() is needed because "cbrt" takes a "double" as input and the "64" will get interpreted as a long. The "toDecimal()" call is necessary to correctly call the method. that the "toNumber()" call is necessary because "cbrt" returns a double and the "max" method is must have parameters of the same type and "5" is interpreted as a long.
-
${literal(5.4):math("scalb", 2)} runs Math.scalb(5.4, 2). This example is important because NiFi EL treats all whole numbers as "longs" and there is no concept of an "int". "scalb" takes a second parameter of an "int" and it is not overloaded to accept longs so it could not be run without special type handling. In the instance where the Java method cannot be found using parameters of type "double" and "long" the "math()" EL function will attempt to find a Java method with the same name but parameters of "double" and "int".
-
${first:toDecimal():math("pow", ${second:toDecimal()})} where attributes evaluate to "first" = 2.5 and "second" = 2. This example runs Math.pow(2.5D, 2D). The explicit calls to toDecimal() are important because of the dynamic nature of EL. When creating the flow, the user is unaware if the expression language values will be able to be interpreted as a whole number or not. In this example without the explicit calls "toDecimal" the "math" function would attempt to run a Java method "pow" with types "double" and "long" (which doesn’t exist).