Nevron Open Vision Documentation
Formula Basics

 
Evaluating Formulas

Formulas are strings, which are evaluated by an instance of the NFormulaEngine class. The formula evaluation produces a single NVariant instance - i.e. the result of the formula evaluation. The following example shows how to evaluate formulas:

My First Formulas
Copy Code
NFormulaEngine formulaEngine = new NFormulaEngine();
NVariant res;

res = formulaEngine.Evaluate("10 + 20");
Console.WriteLine("10 + 20 evaluates to " + res);

res = formulaEngine.Evaluate("10mm + 20in");
Console.WriteLine("10mm + 20in evaluates to " + res);

res = formulaEngine.Evaluate("MIN(10, 20, 30)");
Console.WriteLine("MIN(10, 20, 30) evaluates to " + res);

res = formulaEngine.Evaluate("SUM(10, 20, 30)");
Console.WriteLine("SUM(10, 20, 30) evaluates to " + res);

You can use operators and functions in formulas to perform diverse operations on values of different types.

The rest of this topic focuses on the formula basics, variants and the operators.

See Functions for more information about the available functions.

Formula Elements 

A valid formula is such a string, which is lexically and grammatically correct. 

Formulas are constructed from tokens. Tokens are such substrings from the initial formula string, which cannot be broken into other tokens. A lexically correct formula consists of the following set of tokens:

The formula engine first splits the input formula to a valid set of tokens, that it further processes to construct a grammatically valid tree representation of the formula. The formula tree consists of the following types of elements:

The formula evaluation works with variants. The result of each formula evaluation is a variant too (e.g. a value of certain type - see Variants below).

Variants

Variants are represented by instances of the NVariant structure. Variants are value-type pairs, which facilitate the type conversion of values, as well as the operations with values of different type.

When variants are used in functions or operators that require a value of a certain type, variants are automatically converted to a value of this type. There are several distinct types of variants:

The power of variants is their ability to provide transparent handling of type and measurement unit conversion so that you can perform common mathematical and logical operations, without caring for the actual type of the involved values. For example:

Variants Example
Copy Code
NVariant res1 = new NVariant(20) + new NVariant(30.0);
Console.WriteLine("Addition operator result with numbers: " + res1.ToString());

NVariant res2 = new NVariant(10, NUnit.Millimeter) + new NVariant(20, NUnit.Inch);
Console.WriteLine("Addition operator result with measures: " + res2.ToString());

NVariant res3 = new NVariant(10, NUnit.Meter) / new NVariant(20, NUnit.Second);
Console.WriteLine("Division operator result with measures: " + res3.ToString());

NVariant res4 = new NVariant(10, NUnit.Millimeter) > new NVariant(8, NUnit.Inch);
Console.WriteLine("Comparision operator result: " + res4.ToString());
// Output is:
// Addition operator result with numbers: 50
// Addition operator result with measures: 518 [mm]
// Division operator result with measures: 0.5 [m/s]
// Comparison operator result: false
You can use the NVariant structure to perform arithmetics and comparisons of values of different type. It is especially useful when dealing with measures.
Operators

You can use operators in formulas to perform arithmetic, comparison, logical and bitwise operations as described by the following table:

Arithmetic Operators

Syntax Name Description Examples
+ Unary plus Does nothing - it is defined for completeness with the unary minus.
Argument should be Number, Measure, Array or Empty.
Supports array chaining.
+10
Returns: 10 
- Unary minus Used to establish a number with a negative sign.
Argument should be Number, Measure, Array or Empty.
Supports array chaining.
-10
Returns: -10

-ARRAY(10, 12)
Returns: ARRAY(-10, -12)
^ Exponentiation Raises left to the power of right
Left should be a number or a measure.
Right should be a number.
If either one is empty the result is empty variant.
Supports array chaining.
10 ^ 2
Returns: 100

ARRAY(10, 12) ^ 2
Returns: ARRAY(100, 144)
* Multiplication Multiplies left by right.
Both arguments should be numbers or measures.
If either one is empty the result is empty variant.
Supports array chaining.
10 * 2
Returns: 20

ARRAY(10, 12) * 2
Returns: ARRAY(20, 24)
/ Division

Divides left by right.
Both arguments should be numbers or measures.
If either one is empty the result is empty variant.
Supports array chaining.

10 / 2
Returns: 5

ARRAY(10, 12) / 2
Returns: ARRAY(5, 6)
+ Addition

Adds right to left.
If either argument is a String, performs string concatenation.
If left is DateTime, the right must be a measure from the time dimension.
If left or right argument is measure, the opposite argument needs to be from the same measure dimension. Result is expressed in left argument unit of measure.
Supports array chaining.

10 + 2
Returns: 12

ARRAY(10, 12) + 2
Returns: ARRAY(12, 14)

ARRAY(10, 12) + ARRAY(12, 23)
Returns: ARRAY(22, 35)

10 + "Nevron"
Returns: "10Nevron"

- Subtraction Subtracts right from left.
If left is DateTime, the right must be a measure from the time dimension.
If left or right argument is measure, the opposite argument needs to be from the same measure dimension. Result is expressed in left argument unit of measure.
Supports array chaining.
10 - 2
Returns: 8

ARRAY(10, 12) - 2
Returns: ARRAY(8, 10)

ARRAY(10, 12) - ARRAY(12, 23)
Returns: ARRAY(-2, -11)

Comparison Operators

Syntax Name Description Examples
> Greater than Returns true if left is greater than right. Otherwise returns false.
Supports array chaining.
10 > 2
Returns: true
< Less than Returns true if left is less than right. Otherwise returns false.
Supports array chaining.
10 < 2
Returns: false
>= Greater than or equal to Returns true if left is greater than or equal to right. Otherwise returns false.
Supports array chaining.
10 >= 2
Returns: true
<= Less than or equal to Returns true if left is less than or equal to right. Otherwise returns false.
Supports array chaining.
10 <= 2
Returns: false
== Equal to Returns true if left is equal to right. Otherwise returns false.
Supports array chaining.
10 = 2
Returns: false
!= Not equal to Returns true if left is not equal to right. Otherwise returns false.
Supports array chaining.
10 != 2
Returns: true

Logical operators

Syntax Name Description Examples
&& Logical AND Returns true if both left and right are true, otherwise returns false.
Supports array chaining.
true && false
Returns: false
|| Logical OR Returns true if either left or right is true, otherwise returns false.
Supports array chaining.
true || false
Returns: true
! Logical NOT Unary operator, that returns the inverse boolean value of its argument.
Supports array chaining.
!true
Returns: false

Bitwise Operators

& Bitwise AND Returns a 32-bit binary number in which a bit is set to 1 if the corresponding bit in both left and right are 1. Otherwise, the bit is set to 0. Supports array chaining. 7 & 2
Returns: 2 (7 = 0111, 2 = 0010)
| Bitwise OR Returns a 32-bit binary number in which a bit is set to 1 if the corresponding bit in either left or right is 1. Otherwise, the bit is set to 0. Supports array chaining. 5 | 3
Returns: 7 (5 = 0101, 3 = 0011, 7 = 0111)
~ Bitwise NOT Unary operator, that returns a 32-bit binary number in which a bit is set to 1 if the corresponding bit in the operand is 0. Otherwise, the bit is set to 0. Supports array chaining. ~1
Returns: 2 ^ 32 - 1

Assignment Operators

Syntax Name Description Examples
= Assignment Assigns a value to a local variable. If a local variable is not yet declared, declares a new one. Returns the value of the local variable. a=6; b=3; a+b;
Returns: 9
+= Addition Assignment Assigns the value to a local variable to be equal to sum of the current value and the result of the right argument evaluation.
Does not declare a new local variable, if it does not exist (i.e. the local variable should first reside on the left side of an assignment operator to be declared). Returns the new value of the local variable.
a=6; a+=3
Returns: 9
-= Subtraction Assignment Assigns the value to a local variable to be equal to the subtraction of the current value and the result of the right argument evaluation.
Does not declare a new local variable, if it does not exist (i.e. the local variable should first reside on the left side of an assignment operator to be declared). Returns the new value of the local variable.
a=6; a-=3
Returns: 3
-= Multiplication Assignment Assigns the value to a local variable to be equal to the multiplication of the current value and the result of the right argument evaluation.
Does not declare a new local variable, if it does not exist (i.e. the local variable should first reside on the left side of an assignment operator to be declared). Returns the new value of the local variable.
a=6; a*=3
Returns: 18
-= Division Assignment Assigns the value to a local variable to be equal to the division of the current value and the result of the right argument evaluation.
Does not declare a new local variable, if it does not exist (i.e. the local variable should first reside on the left side of an assignment operator to be declared). Returns the new value of the local variable.
a=6; a/=3
Returns: 2
-= Exponentiation Assignment Assigns the value to a local variable to be equal to the exponentiation of the current value and the result of the right argument evaluation.
Does not declare a new local variable, if it does not exist (i.e. the local variable should first reside on the left side of an assignment operator to be declared). Returns the new value of the local variable.
a=6; a^=3
Returns: 216

Array chaining, in the context of operators is the ability to pass as argument(s) an array variant. For example:

ARRAY(10,20) + 5, evaluates to ARRAY(15,25).
ARRAY(10,20) + ARRAY(5, 15, 30), evaluates to ARRAY(15,35).
-ARRAY(10,20), evaluates to ARRAY(-10,-20)

There is a certain precedence assigned to each operator. If an expression contains several operators, which are not enclosed in parentheses, the operator with the highest precedence is evaluated first. For example:

10 + 20 * 2 - evaluates to 50, because the multiplication operator will be evaluated first (it has a higher precedence than the addition operator).

(10 + 20) * 2 - evaluates to 60, since the parentheses override the default way in which the expression is evaluated.

The following table summarizes the operators precedence, in high to low order.

Category Operators
Primary Unit Operators ([mm], [in], [m], [s], [m/s] etc.)
Unary Unary Plus (+), Unary Minus (-), Logical Not (!), Bitwise Not (~)
Power Exponentiation (^)
Multiplicative Multiplication (*), Division (/)
Additive Addition (+), Subtraction (-)
Relational Greater Than (>), Less Than (<), Greater Than Or Equal To (>=), Less Than Or Equal To (<=)
Equality Equal To (=), Not Equal To (!=)
Bitwise AND Bitwise AND (&)
Bitwise OR Bitwise OR (|)
Logical AND Logical AND (&&)
Logical OR Logical OR (||)
Assignment Assignment (=)

There is also a left or right associativity assigned to each operator. The associativity determines the execution order of operators with the same precedence. The Assignment (=) and the Exponentiation (^) operators have right associativity. All other operators have left associativity.

To demonstrate the effect of right versus left associativity consider the following expression:

5^2^3 - evaluates to 390625 (5^(2^3) = 390625), which is different than (5^2)^3=15625, because the Exponentiation has right associativity.

Send Feedback