--- title: "Define calculations" slug: "define-calculations" updated: 2025-04-02T19:00:41Z published: 2025-04-02T19:00:41Z canonical: "docs.zilliant.com/define-calculations" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.zilliant.com/llms.txt > Use this file to discover all available pages before exploring further. # Define calculations Use calculations to compute new information during the configuration process. Defined as arithmetic equations or formulas, they handle tasks such as cost estimation based on user input and calculating other dependent parameters. For example, for a product made of metal, calculations can determine the area based on its length and width. Then, the [pricing engine](/v1/docs/internal-pricing-engine) can use this calculated area to estimate the metal product cost. Tip The pricing engine calculates the cost, while the calculation engine calculates the area. Calculations are defined in the [product knowledge base](/v1/docs/create-a-knowledge-base) and compute the values of Dynamic Data [Attributes](/v1/docs/about-dynamic-attributes) (DDA) and Dynamic Symbolic Attributes (DSA) of the numeric type. However, you can perform assignments only on numeric DDAs. Using basic BODMAS principles combined with arithmetic functions, calculations can handle anything from simple estimations to complex computations. Tip [IMCScript](/v1/docs/about-imcscript) offers a more powerful tool set to set up custom calculations in the model. However, IMCScript applies to the whole system, while calculations apply only to a specific knowledge base. ## Create a calculation 1. [Create a dynamic data attribute (DDA) of the numeric type.](/v1/docs/create-dynamic-attributes) 2. [Add the DDA to the product knowledge base.](/v1/docs/add-dynamic-attributes-to-products) 3. [Group the attributes in the product knowledge base.](/v1/docs/group-dynamic-attributes-in-a-knowledge-base) 4. In the knowledge base, go to the **Calculations** tab by following these steps: 1. From the application left navigation area, select **Products**. 2. Select a product. 3. From the top navigation bar, select **Knowledge Base**. 4. Select a knowledge base, then go to the **Calculations** tab. 5. Select ![](https://cdn.document360.io/24f960e8-3c1c-4c18-a2c6-83b6ae4aab84/Images/Documentation/CPQ-icon_add.png?sv=2026-02-06&spr=https&st=2026-11-02T13%3A47%3A28Z&se=2026-11-02T14%3A47%3A28Z&sr=c&sp=r&sig=TxLGYhLTshHQI3X2NrqaoTBgNVJIrHLCrJersJ3z7tI%3D) to create a calculation. 6. On the **Create New Calculation** dialog, enter the following information: - **Name**—Enter a name for the calculation, for example the name of your dynamic attribute. - **Arithmetic Expression**—Enter an arithmetic expression including one or multiple numeric dynamic attributes. Use the **$()** syntax to add a dynamic attribute. 7. [Create a knowledge base snapshot.](/v1/docs/create-a-knowledge-base-snapshot) In the [product configurator](/v1/docs/work-with-product-configurator), users can't edit the value of the dynamic attribute, whose value is computed based on a calculation. ## Calculation features - Includes various checks such as cyclic dependency detection, cast exceptions, divide-by-zero exceptions, and unacceptable syntax validation. - Includes several built-in functions from the Jexl library, such as substring() for strings and size() for various objects. - Supports basic mathematical operators (+, -, *, /, %) and includes additional constants and custom functions. - Allows nested function calls, for example, `min(max(5, 2, pow(2, 3)), 20, 30)`. - Unlike the conventional Java math library, we support dynamic variable lengths for custom functions. For example, you can calculate GCD, LCM, or AVG for multiple variables in a single function call, such as `gcd(12, 24, 36, 40)`. ## Calculation performance All functions execute with an average duration of less than 0.1 ms. We conducted the performance tests on a system with the following specifications: - Processor: Core i5 - Memory: 8 GB RAM - Operating system: Windows 10 Pro, 64-bit We used a typical machine after startup, parameters, for example arrays, of up to 5 elements and relatively small integers and strings. Actual performance may vary based on specific use cases and system configurations. ## Libraries ### Constant library The `Math.` prefix can use defined here functions, for example, `Math.PIE`, `Math.E`, or `Math.EQ`. #### Standard constants | Constant | Value | | --- | --- | | PIE π | 3.14159265358979323846, ratio of circumference to its diameter. | | E e | 2.7182818284590452354, the base of natural algorithms. | #### Conditional constants | Constant | Function | | --- | --- | | EQ | Defines Equivalence relation (==) between 2 operands. | | NEQ | Defines Not-equivalence relation (!=) between 2 operands. | | LT | Defines Less than relation (<) between 2 operands. | | LTE | Defines Less than and equals to relation (<=) between 2 operands. | | GT | Defines Greater than relation (>) between 2 operands. | | GTE | Defines Greater than and equals to relations (>=) between 2 operands. | #### Directional constants | Constant | Functions | | --- | --- | | ASC | Depending on the use case context, defines ascending direction for any operation. | | DESC | Depending on the use case context, defines descending direction for any operation. | ### Standard functions | Function | Description | Example | | --- | --- | --- | | Summation | `sum(Number... nVals) : Double` Computes the sum of all provided values. | `sum([10, 20, 30])` = 60.0 `sum([5, 15, 25, 100])` = 145.0 | | Multiplication | `mul(Number... nVals) : Double` Computes the multiplication of all provided values. | `mul([1, 2, 3])` = 6.0 `mul(2, 3, 5, 1)` = 30.0 | | Absolute | `abs(Number n) : Double` Returns the absolute value of the provided number. | `abs(-7)` = 7.0 | | Count | `count(Number... nVals) : Integer` Counts the number of provided arguments or elements in an array. This function is similar to Jexl's default `size` method. | `count([4, 5])` = 2 `count(1, 2, 3, 4, 5)` = 5 | | Maximum | `max(Number... nVals) : Double` Returns the largest number among the provided numbers. | `max(4, 11)` = 11.0 `max(1, 2, 7, 9)` = 9.0 | | Average | `avg(Number... nVals) : Double` Computes the average of the provided values. This function is equivalent to the `Mean` function in statistics. | `avg(4, 7)` = 5.5 `avg(6, 4.5, 11.5, 2)` = 6.0 | | Greatest Common Divisor (GCD) | `gcd(Number... nVals) : Integer` Calculates the greatest common divisor (GCD) of the provided numbers. | `gcd(24, 18)` = 6 `gcd(50, 24, 18)` = 2 | | Least Common Multiple (LCM) | `lcm(Number... nVals) : Integer` Calculates the least common multiple (LCM) of the provided numbers. | `lcm(16, 4)` = 16 `lcm(32, 12, 16, 2)` = 96 | ### Convergence functions | Function | Description | Example | | --- | --- | --- | | Round | `round(Number n, Number decimal) : Double` Rounds the number to the specified decimal digits. If the second argument is not provided, the default decimal digits will be 2. | `round(3.1345964, 4) = 3.1346` `round(3.1345964) = 3.13` | | Ceil | `ceil(Number n) : Double` Finds the ceiling value of a number. | `ceil(7.345) = 8.0` `ceil(-7.345) = -7.0` | | Floor | `floor(Number n) : Double` Finds the floor value of a number. | `floor(7.345) = 7.0` `floor(-7.345) = -8.0` | ### Statistical functions | Function | Description | Example | | --- | --- | --- | | Mean | `mean(Number… nVals) : Double` Finds the mean of the provided numbers. This function is the same as the Average function in the list of [standard functions](/v1/docs/define-calculations#standard-functions). | `mean(4, 7) = 5.5` `mean(6, 4.5, 11.5, 2) = 6.0` | | Median | `median(Number… nVals) : Double` Finds the median of the provided numbers. | `median(3, 2, 7, 1, 9, 2, 10) = 3.0` `median(1, 2, 3, 4, 5, 6) = 3.5` | | Mode | `mode(Number… nVals) : Double` Finds the mode of the provided numbers. This function doesn’t guarantee any order of outcomes (modes). | `mode(8, 2, 7, 2, 9, 2, 10) = [2.0]` `mode(1, 3, 3, 4, 2, 5, 2) = [3.0, 2.0]` `mode(1, 2, 3, 4, 5) = []` `mode(1, 1, 2, 2, 3, 3) = [1.0, 2.0, 3.0]` | ### Exponential functions | Function | Description | Example | | --- | --- | --- | | Power | `pow(Number n, Number exponent) : Double` Finds the nth power of the number. | `pow(2, 3) = 8.0` `pow(5, 2) = 25.0` | | Root | `root(Number n, Number root) : Double` Finds the nth root of the number. If multiple roots exist, the function returns only the positive root. | `root(16, 4) = 2.0` `root(3, 2) = 1.7320508075688772` | | Square | `sq(Number n) : Double` Finds the square of a number. This is a special case of the Power method with an exponent of 2; hence, it’s equivalent to calling `pow(n, 2)`. | `sq(3) = 9.0` | | Cube | `cube(Number n) : Double` Returns the cube of a number. This is a special case of the Power method with an exponent of 3; hence, it’s equivalent to calling `pow(n, 3)`. | `cube(3) = 27.0` | | Square-Root | `sqrt(Number n) : Double` Returns the positive square root of a number. This is a special case of the Root method with root 2; hence, it’s equivalent to calling `root(n, 2)`. | `sqrt(25) = 5.0` | | Cube-Root | `cbrt(Number n) : Double` Returns the cube root of a number. This is a special case of the Root method with root 3; hence, it’s equivalent to calling `root(n, 3)`. | `cbrt(27) = 3.0` | ### Trigonometric functions | Function | Description | Example | | --- | --- | --- | | Degree to Radian | `rad(Number degree) : Double` Converts degrees to radians. | `rad(50) = 0.8726646259971648` | | Radian to Degree | `deg(Number radian) : Double` Converts radians to degrees. | `deg(0.8726646259971648) = 50` | | Sine | `sin(Number radian) : Double` Returns the sine value of a radian. | `sin(0) = 0.0` `sin(rad(45)) = 0.7071067811865475` | | Cosine | `cos(Number radian) : Double` Returns the cosine value of a radian. | `cos(0) = 1.0` `cos(rad(45)) = 0.7071067811865476` | | Tangent | `tan(Number radian) : Double` Returns the tangent value of a radian. | `tan(0) = 0.0` `tan(rad(45)) = 0.9999999999999999` | | Arc-Sine | `asin(Number value) : Double` Returns the arc-sine (inverse of the sine function) of a value. | `asin(0.70) = 0.775397496610753` `asin(sin(1)) = 1.0` | | Arc-Cosine | `acos(Number value) : Double` Returns the arc-cosine of a value (inverse of the cosine function). | `acos(0.70) = 0.7953988301841436` `acos(cos(1)) = 1.0` | | Arc-Tangent | `atan(Number value) : Double` Returns the arc-tangent of a value (inverse of the tangent function). | `atan(0.70) = 0.6107259643892086` `atan(tan(1)) = 1.0` | ### Logarithmic functions | Function | Description | Example | | --- | --- | --- | | Logarithm | `log (Number number, Number base) : Double` Calculates and returns the logarithmic value of a number using the provided base. If the second argument is absent, the default base will be considered as e = 2.718281828459045, which is the base of natural logarithms. | `log (100,10) = 2.0` `log (100) = 4.605170185988092` | | Logarithm with base 10 | `log10 (Number number) : Double` Calculates and returns the logarithmic value of a number using base 10. This is a special case of the Logarithm method with base 10, hence it’s the same as calling `log(n,10)`. | `log10 (100) = 2.0` | ### Casting functions | Function | Description | Example | | --- | --- | --- | | To Integer (String) | `toInteger (String s, Integer default) : Integer` Converts the provided String to Integer type. If any exception occurs during execution (for example, CastException), it will return the default value provided as the second argument. `toInteger (String[] sArray, Integer default) : Integer` Converts the provided String array to an Integer array. If any exception occurs during conversion of any element (for example, CastException), it will return the default value provided as the second argument. **Note:** If the second argument is of the Double type, it will consider its Integer part as the default value. | `toInteger("11.3",5) = 11` `toInteger("11",5) = 11` `toInteger("abc",5) = 5` `toInteger("def") = 0` `toInteger("abc",5.5) = 5` `toInteger(["5", "6"],5.5) = [5, 6]` `toInteger(["7", "a"],5.5) = 5.5` | | To Integer (Number) | `toInteger (Number n, Integer default) : Integer` Converts the provided Number to Integer type. If any exception occurs (for example, unacceptable numbers like NaN/Infinity/-Infinity), it will return the default value provided as the second argument. `toInteger (Number[] nArray, Integer default) : Integer` Converts the provided Number array to Integer array. If any exception occurs (for example, unacceptable numbers like NaN/Infinity/-Infinity), it will return the default value provided as the second argument. **Note:** If the second argument is of the Integer type, it will convert it to Double and consider it as the default value. | `toInteger(31.3,5) = 31` `toInteger(31,5) = 31` `toInteger(NaN,0) = 0` `toInteger(log(0),0) = 0` `toInteger([8.5,3.6],5) = [8,6]` `toInteger([8.5,NaN],5) = [8,5]` | | To Double (String) | `toDouble (String s, Number default) : Double` Converts the provided String to Double type. If any exception occurs (for example, CastException), it will return the default value provided as the second argument. `toDouble (String[] sArray, Number default) : Double` Converts the provided String array to an array of Double type. If any exception occurs during conversion of any element (for example, CastException), it will return the default value provided as the second argument. **Note:** If the second argument is of the Integer type, it will convert it to Double and consider it as the default value. | `toDouble("11.3",5.0) = 11.3` `toDouble("11",5.0) = 11.0` `toDouble("abc",5.0) = 5.0` `toDouble("abc",5) = 5.0` `toDouble(["11","13"],5.0) = [11.0,13.0]` `toDouble(["11","b"],5.0) = [11.0,5.0]` | | To Double (Number) | `toDouble (Number… nVals) : Double` Converts the provided Number to Double type. | `toDouble(40) = 40.0` `toDouble(51.87) = 51.87` `toDouble(40,50) = [40.0,50.0]` | | To String | `toString (Number nVals) : String` Converts the provided Number to String type. | `toString(11) = "11.0"` `toString(11.3,5.0) = ["11.3", "5.0"]` | ### Check functions | Function | Description | Example | | --- | --- | --- | | Is Finite | `isFinite (Number n) : Boolean` Checks if the number is finite or not. Returns **true** if the argument is a finite value; returns **false** otherwise (for **NaN** and **Infinity** arguments). | `isFinite(0.70) = true` `isFinite(log(0)) = false` `isFinite(NaN) = false` | | Is Not-A-Number | `isNaN (Number n) : Boolean` Checks if the number is not a number (NaN) or not. Returns true if the argument is NaN; returns **false** otherwise. | `isNaN(NaN) = true` `isNaN(0.70) = false` `isNaN(log(0)) = false` | | Is Null | `isNull (Number n) : Boolean` Checks if the argument is null or not. Returns **true** if the argument is null; returns **false** otherwise. | `isNull(null) = true` `isNull(log(0)) = false` `isNull(NaN) = false` | ### Conditional functions | Function | Description | Example | | --- | --- | --- | | If | `iff(Boolean condition, Number numberIfTrue, Number numberIfFalse) : Number` This conditional function works like a ternary operator, returning a value based on the outcome of the condition (first argument). | `iff(10 < 5, 1, 0) = 0` `iff(round(sin(rad(45))) == round(cos(rad(45))), 1, 0) = 1` | | Filter If | `filterIf(Number[] nArray, Constant condition, Number compareTo) : Number[]` Filters an array based on the provided mathematical condition, using the last two arguments. Here the second argument is a conditional constant: `Math.EQ`, `Math.NEQ`, `Math.LT`, `Math.LTE`, `Math.GT`, `Math.GTE`. **Note:** You can also use strings like `">="` instead of constants for better readability. An incorrect condition results in an empty array. | `filterIf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], Math.GT, 5) = [6, 7, 8, 9, 10]` `filterIf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], Math.LTE, 5) = [1, 2, 3, 4, 5]` `filterIf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ">=", 8) = [8, 9, 10]` | | Count If | `countIf(Number[] nArray, Constant condition, Number compareTo) : Integer` Counts the number of elements in an array that meet the specified condition. Internally, this method calls `Filter If` and then `Count`. **Note:** An incorrect condition returns 0 as the result. | `countIf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], Math.GT, 5) = 5` | ### Special functions #### Before you begin - Keep special cases in mind when using these functions, such as `NaN`, `+Infinity`, `-Infinity`, and `null`, as they may return results like `NaN`, `+Infinity`, `-Infinity`, or other values depending on the case. - Avoid passing one or more null arguments, as this typically results in `NaN` (or a default argument, if specified). We do not recommend providing `NaN` or `null` in arguments to prevent unexpected results. - All function and constant names are case-sensitive and signature-sensitive. Follow the correct syntax and signatures to avoid errors. - Functions with a single parameter of variable argument types (for example, `Double...`, `String...`) allow flexibility. You can pass either an array or variable arguments. For example, `max(3,4,5)` returns the same result as `max([3,4,5])`. - Calculations are currently limited to the same knowledge base. You cannot access DAs from another product’s knowledge base or from parent/child attributes of a SalesItem. However, you can use Search Expressions to bridge this gap. - Avoid using the `SearchExpression` method unless absolutely necessary. If you must use it, review the notes associated with it beforehand. - The distinction between type and types keywords has been simplified for search expressions. Previously, type and types behaved differently, but now only the type keyword exists. It returns a collection of all object types, making the syntax more generic for various use cases. You can still retrieve a single type of object using the first keyword, as shown in the following table. When migrating legacy search expressions, update their syntax to align with this change. | Old syntax | New syntax | | --- | --- | | SalesItem.type.endsWith('Stamping') | SalesItem.type.first().endsWith('Stamping') | | SalesItem.types.ID | SalesItem.type.ID | #### Functions | Function | Description | Example | | --- | --- | --- | | Sort | `sort(Number[] nArray, Constant direction) : Boolean` Sorts the provided array (`nArray`) in the specified direction (`direction`). Direction can be one of the constants: `Math.ASC` (ascending) or `Math.DESC` (descending). **Note:** Defaults to `Math.ASC` if direction is not provided. Invalid direction values result in an unsorted array. Handles special cases: `+Infinity`, `-Infinity`, and `NaN` based on Java comparator conventions. | `sort([4,3,6,9,5], Math.ASC) = [3,4,5,6,9]` `sort([4,3,6,9,5], Math.DESC) = [9,6,5,4,3]` `sort([10,NaN,-log(0),log(0)]) = [-Infinity, 10, +Infinity, NaN]` | | Distinct | `dist(Number[] nArray) : Number[]` Returns an array of distinct elements from the provided array. This function doesn't guarantee any specific order for the output array. | `dist([5,3,4,4,5]) = [3,4,5]` `dist([10,2,3,10,2]) = [2,3,10]` | | Concatenate | `concat(String[] sArray1, String[] sArray2) : String[]` Concatenates corresponding elements of two arrays and returns the result as a new array. **Note:** Null values are treated as empty strings. The resulting array length equals the maximum length of the input arrays. | `concat(["a","b","c"], ["1","2",null]) = ["a1","b2","c"]` `concat(["a","b","c"], ["1","2"]) = ["a1","b2","c"]` `concat(["a","b"], ["1","2","3"]) = ["a1","b2","3"]` | | Concatenate | `concat(String... sArgs) : String` Concatenates one or more string arguments into a single string. **Note:** Null arguments are treated as empty strings. | `concat("a","b","c") = "abc"` `concat("a","b",null) = "ab"` | | Mapper | `map(String[] sArray, Map<String,String> sMap) : String[]` Updates an array (`sArray`) by replacing each element using a provided map (`sMap`). Missing keys leave the element unchanged. | `map(["a","b","c"], {"a":"1","b":"2","c":"3"}) = ["1","2","3"]` `map(["a","b","c","d"], {"a":"1","b":"2","c":"3"}) = ["1","2","3","d"]` | | Mapper | `map(Number[] nArray, Map<Number, Number> nMap) : Double[]` Updates a numeric array (`nArray`) by replacing elements using a provided map (`nMap`). Missing keys leave the element unchanged. | `map([1,2,3], {1:11,2:22,3:33}) = [11.0,22.0,33.0]` `map([1,2,3], {1.0:11,2:22,3:33.0}) = [11.0,22.0,33.0]` `map([1,2,3,4], {1:11,2:22,3:33}) = [11.0,22.0,33.0,4.0]` | | Search Expression | `se(String expression).as<<TYPE>>(TYPE defaultObj) : TYPE` Enables traversing between object levels (for example, parent `SalesItem` and its children). **Syntax:** - `se`—Accepts a search expression as a string (starts with `"ConfigItem"`). - `as<<TYPE>>`—Specifies the expected return type (`Number`, `String`, `SArray`, or `NArray`). If the expression is null or an error occurs, returns `defaultObj`. **Note:** This experimental function has performance limitations and lacks validation for nested dependencies. Consider alternate options like triggers or additional DAs for complex use cases. | `se("ConfigItem.configItemIncludedBy.children().getDAValue('DA1')").asNArray([]) = [10,20,30]` `se("ConfigItem.configItemIncludedBy.objectName").asString('No_Name') = "SalesItem1"` | Mnemonic term for *order of operations*, the collection of rules for which operations to perform first to evaluate a mathematical expression. **BODMAS** stands for **B**rackets, **O**rder, **D**ivision/**M**ultiplication, and **A**ddition/**S**ubtraction.