Skip to main content

Arithmetic and Comparison Operators

Most logic eventually comes down to math: counting, scaling, comparing. This page covers the operators you'll use, the built-in math functions, and the rounding rules you need to know when integers and decimals meet.

Modeled on Studio 5000 Logix Designer

rungs.dev models its math behavior on Studio 5000 Logix Designer® — division, rounding, and type coercion follow the same conventions. Rare edge cases may differ.

Arithmetic Operators

OperatorDescriptionExample
+AdditionTotal := A + B;
-SubtractionDelta := A - B;
*MultiplicationProduct := A * 5;
/DivisionAverage := Sum / Count;
MODRemainderRemainder := A MOD B;

Use parentheses to control the order, just like in regular math:

Result := (Value1 + Value2) * 3;

Comparison Operators

Comparison operators ask a true/false question. They show up most often inside an IF.

OperatorDescriptionExample
=Equal toIF Mode = 1 THEN
<>Not equal toIF State <> 0 THEN
<Less thanIF Temp < 100 THEN
>Greater thanIF Speed > Limit THEN
<=Less than or equalIF Level <= 50 THEN
>=Greater or equalIF Count >= Max THEN

Division: integers vs decimals

Division is the operator that surprises people most often, because the result depends on what you're dividing into. The destination tag's type decides whether you keep the fraction or lose it.

Try this in your head: 7 / 2. The exact answer is 3.5. What you get in the tag depends on where you're putting it:

DintResult := 7 / 2; // DintResult = 3 — integer truncation
RealResult := 7 / 2; // RealResult = 3.5 — fraction preserved
DintResult := 7.0 / 2; // DintResult = 4 — see "Banker rounding" below

The full rule:

Left operandRight operandDestinationWhat you get
DINTDINTDINTInteger division (truncates to zero)
DINTDINTREALFloat division (fraction preserved)
any REALanyDINTFloat division, then banker rounding
any REALanyREALFloat division

A small detail worth knowing: integer division always truncates toward zero, not down. So -7 / 2 is -3, not -4.

Banker rounding (REAL into DINT)

When you put a decimal value into a DINT, Studio uses banker rounding — also called round half to even.

You probably learned in school: round halves up (0.5 → 1, 1.5 → 2, 2.5 → 3, 3.5 → 4). Banker rounding does something slightly different — when the value is exactly halfway, it rounds to the nearest even number:

ValueSchool roundingBanker rounding
0.510
1.522
2.532
3.544
-2.5-2-2
-3.5-3-4

For values that aren't exactly halfway, banker rounding works the same as normal rounding: 1.4 → 1, 1.6 → 2.

Why use it? Because rounding all halves up adds a small bias: if you round many measurements over and over, the total drifts a little high. Banker rounding splits halves evenly between rounding up and rounding down, so the bias cancels out. Industrial controllers and financial systems use it for the same reason.

DintSetpoint := RealSetpoint; // banker rounding applied automatically

Division by zero

Dividing by zero is normally an error. Studio handles it without crashing the program. The result depends on the operand types and the destination type:

What you wroteWhat you get
DintDest := 5 / 0;DintDest = 5 — Source A copied (DINT/DINT)
DintDest := 0 / 0;DintDest = 0 — Source A copied
DintDest := 5.0 / 0.0;DintDest = 2147483647+Infinity clamps to MAX_DINT
DintDest := -5.0 / 0.0;DintDest = -2147483648-Infinity clamps to MIN_DINT
DintDest := 0.0 / 0.0;DintDest = 0NaN becomes 0
RealDest := 5.0 / 0.0;RealDest = +Infinity
RealDest := 0.0 / 0.0;RealDest = NaN ("Not a Number")

For a DINT destination, all-DINT division copies the left operand (Source A); when any operand is REAL, the float result is clamped into the DINT range so you never see Infinity in an integer tag. A REAL destination keeps the raw +Infinity, -Infinity, or NaN value. The program keeps running in every case.

If you want to handle a possible zero divisor explicitly, check for it first:

IF Divisor <> 0 THEN
Result := Numerator / Divisor;
ELSE
Result := 0; // or whatever fallback makes sense
END_IF;

Built-in math functions

These are the math functions you can call from any expression:

FunctionWhat it does
ABS(x)Absolute value (drops the minus sign).
SQRT(x)Square root. Negative inputs become SQRT(ABS(x)).
SIN(x)Sine of x, where x is in radians.
COS(x)Cosine of x, in radians.
TAN(x)Tangent of x, in radians.
DintDest := ABS(-7); // 7
RealDest := SQRT(-1.0); // 1.0 — never NaN, never an error
RealDest := SIN(0.0); // 0.0

There is no MIN or MAX function. Use IF/ELSE:

// "Smaller" = MIN(A, B)
IF A < B THEN
Smaller := A;
ELSE
Smaller := B;
END_IF;

Numeric literals

Numbers you type directly into your code are called literals.

FormTypeExample
42DINTCounter := 42;
-42DINTOffset := -42;
3.14REALPi := 3.14;
1.0e3REALScale := 1.0e3;
2.5E-2REALGain := 2.5E-2;

Scientific notation must include a decimal point: write 1.0e3, not 1e3. The decimal point is what tells Studio you mean a REAL value.

Putting it together

// Add two values and scale the result
Result := (Value1 + Value2) * 3;

// Trigger an alarm if temperature exceeds 100
IF Temperature > 100 THEN
Alarm := 1;
END_IF;

// Convert raw ADC count (0-4095) into a percentage (0-100)
// REAL destination keeps the fraction — RawCount = 2047 gives ~49.988
ScaledReal := (RawCount * 100) / 4095;

// Same expression into a DINT — RawCount = 2047 gives 49 (truncated, not rounded)
DintScaled := (RawCount * 100) / 4095;

// Round a REAL setpoint to the nearest DINT (banker rounding applies)
DintSetpoint := RealSetpoint;