Operators in RPG
Learn arithmetic, comparison, logical, and assignment operators in modern free-form RPG IV, including the %DIV and %REM built-in functions and operator precedence
Operators are the verbs of expression-based programming: they take values and combine them into new ones. Modern free-form RPG IV evaluates expressions much like any other procedural language, using familiar infix operators (+, -, *, /) inside EVAL-style assignments. This is a significant departure from classic fixed-format RPG, where arithmetic was expressed through operation codes like ADD, SUB, and MULT spread across factor columns.
Because RPG was built for business data processing, its operator set is tuned for precise decimal arithmetic. The language leans on packed and zoned decimal types to avoid the rounding surprises of binary floating point, and it provides built-in functions (BIFs) such as %DIV and %REM for integer division and remainders rather than a dedicated % operator. This tutorial covers arithmetic, comparison, logical, assignment, and string operators, plus how RPG resolves operator precedence.
All examples use fully free-form syntax (the **FREE directive on line 1). As with every RPG program on this site, the code is shown and explained here, but running it requires access to an IBM i system — there is no open-source RPG compiler or Docker image.
Arithmetic Operators
RPG supports the standard arithmetic operators in expressions: + (add), - (subtract), * (multiply), / (divide), and ** (exponentiation). Integer division and remainder are handled by the %DIV and %REM built-in functions rather than operators.
Create a file named arithmetic.rpgle:
**FREE
dcl-s a int(10) inz(17);
dcl-s b int(10) inz(5);
dcl-s realDiv packed(7:3);
dcl-s power int(20);
// Basic arithmetic operators
dsply ('a + b = ' + %char(a + b)); // addition
dsply ('a - b = ' + %char(a - b)); // subtraction
dsply ('a * b = ' + %char(a * b)); // multiplication
// True division keeps decimal places in a packed field
realDiv = a / b;
dsply ('a / b = ' + %char(realDiv));
// Integer division and remainder use BIFs, not operators
dsply ('%div = ' + %char(%div(a:b)));
dsply ('%rem = ' + %char(%rem(a:b)));
// Exponentiation
power = b ** 2;
dsply ('b ** 2 = ' + %char(power));
*inlr = *on;
Notes on RPG’s arithmetic model:
%charconverts a numeric value to its character form so it can be concatenated into thedsplymessage. RPG has no implicit number-to-string coercion.a / bstores3.400because the result fieldrealDivispacked(7:3)— the decimal positions of the result field control the precision, not the operands.%div(a:b)truncates toward zero, giving3, while%rem(a:b)returns the remainder2.**is exponentiation;b ** 2is25.
Comparison and Logical Operators
Comparison operators produce a true/false result used in IF, DOW, DOU, and WHEN conditions. RPG uses = for equality (not ==) and <> for “not equal”. The logical operators are the keywords AND, OR, and NOT rather than symbols.
Create a file named comparison.rpgle:
**FREE
dcl-s x int(10) inz(10);
dcl-s y int(10) inz(20);
dcl-s age int(10) inz(25);
dcl-s hasLicense ind inz(*on);
// Relational operators: = <> < > <= >=
if x < y;
dsply 'x is less than y';
endif;
if x <> y;
dsply 'x is not equal to y';
endif;
// Logical AND
if age >= 18 and hasLicense;
dsply 'Can drive';
endif;
// Logical OR / NOT
if age < 18 or not hasLicense;
dsply 'Cannot drive';
else;
dsply 'All requirements met';
endif;
*inlr = *on;
Key points:
- Equality is a single
=. Because RPG uses=for both assignment and comparison, context (anIFcondition vs. a free-form assignment statement) determines the meaning. indis RPG’s indicator (boolean) type. An indicator evaluates directly in a condition, soand hasLicenseneeds no= *on.*onand*offare the boolean literals (equivalent to'1'and'0').
Assignment and Compound Operators
The = operator assigns a value. Free-form RPG also supports compound assignment operators — +=, -=, *=, /=, and **= — which update a variable in place.
Create a file named assignment.rpgle:
**FREE
dcl-s total int(10) inz(100);
total += 50; // total = total + 50
dsply ('After += 50: ' + %char(total));
total -= 30; // total = total - 30
dsply ('After -= 30: ' + %char(total));
total *= 2; // total = total * 2
dsply ('After *= 2: ' + %char(total));
total /= 4; // total = total / 4
dsply ('After /= 4: ' + %char(total));
*inlr = *on;
Compound operators are purely shorthand: total += 50 is identical to total = total + 50. They were added with free-form calculations and are unavailable in fixed-format RPG, which relied on the ADD, SUB, MULT, and DIV operation codes instead.
String Operators
In RPG the + operator concatenates character strings as well as adding numbers. Because fixed-length char fields are blank-padded to their full size, you typically combine + with the %TRIM built-in function to remove trailing blanks. Variable-length varchar fields concatenate cleanly without padding.
Create a file named strings.rpgle:
**FREE
dcl-s firstName varchar(20) inz('Hello');
dcl-s lastName varchar(20) inz('World');
dcl-s message varchar(50);
dcl-s padded1 char(10) inz('Hello');
dcl-s padded2 char(10) inz('World');
// varchar concatenation needs no trimming
message = firstName + ', ' + lastName + '!';
dsply message;
// char fields are blank-padded, so trim before joining
dsply (%trim(padded1) + ' ' + %trim(padded2));
*inlr = *on;
Without %trim, the fixed char(10) fields would concatenate as 'Hello World ' (with embedded blanks). %trim strips the leading and trailing spaces so the result is Hello World.
Operator Precedence
When an expression mixes operators, RPG evaluates them in a defined order. Exponentiation (**) binds tightest, followed by unary minus, then multiplication and division, then addition and subtraction, and finally the comparison and logical operators. Use parentheses to override the default order.
Create a file named precedence.rpgle:
**FREE
dcl-s result int(10);
// * binds tighter than +
result = 2 + 3 * 4;
dsply ('2 + 3 * 4 = ' + %char(result)); // 14
// Parentheses force addition first
result = (2 + 3) * 4;
dsply ('(2 + 3) * 4 = ' + %char(result)); // 20
// ** binds tighter than +
result = 2 ** 3 + 1;
dsply ('2 ** 3 + 1 = ' + %char(result)); // 9
*inlr = *on;
From highest to lowest precedence in RPG expressions:
**(exponentiation)- unary
-and+,NOT *and/- binary
+and- = <> < > <= >=(comparison)ANDOR
Running on IBM i
RPG runs exclusively on IBM i — there is no open-source compiler and no Docker image is available, so these examples cannot be run on Linux, macOS, or Windows. If you have access to an IBM i system, compile and run each source file with CL (Control Language) commands. For example, to build and run arithmetic.rpgle:
| |
Repeat for the other files (comparison.rpgle, assignment.rpgle, strings.rpgle, precedence.rpgle), changing the program name and source path. Options for getting IBM i access include the free public PUB400.COM system, IBM Power Virtual Server cloud instances, and IBM i Access Client Solutions.
Expected Output
Each dsply sends one message to the program message queue (shown plainly below; in a batch job log each line is prefixed with DSPLY).
arithmetic.rpgle:
a + b = 22
a - b = 12
a * b = 85
a / b = 3.400
%div = 3
%rem = 2
b ** 2 = 25
comparison.rpgle:
x is less than y
x is not equal to y
Can drive
All requirements met
assignment.rpgle:
After += 50: 150
After -= 30: 120
After *= 2: 240
After /= 4: 60
strings.rpgle:
Hello, World!
Hello World
precedence.rpgle:
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
2 ** 3 + 1 = 9
Key Concepts
- Free-form expressions replaced classic operation codes —
total = a + bis the modern equivalent of fixed-formatADD,SUB,MULT, andDIV. - Equality uses a single
=, and “not equal” is<>; the same=symbol serves for both assignment and comparison depending on context. %DIVand%REMprovide integer division and remainder — RPG has no%modulo operator.- The result field’s decimal positions control arithmetic precision, which is why business-grade packed decimals avoid floating-point rounding errors.
- Compound assignment operators (
+=,-=,*=,/=,**=) are free-form-only shorthand for updating a variable in place. - Logical operators are keywords —
AND,OR,NOT— and indicators (ind) evaluate directly in conditions without comparing to*on. +concatenates strings, and pairing it with%TRIMremoves the blank padding inherent to fixed-lengthcharfields.- Precedence runs
**→ unary →*/→+-→ comparison →AND→OR; use parentheses to make intent explicit.
Comments
Loading comments...
Leave a Comment