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:

Table 1. Table 24. toRadix Examples
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:

Table 2. Table 25. toRadix Examples
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).