RPGLE Numeric and Conversion BIFs Reference

This page is a lookup for the RPGLE numeric and conversion built-in functions: what each one takes, what it returns, and the rounding and truncation rules that cause wrong totals. For how numeric fields are stored and how many digits they hold, read RPGLE Data Types, Lengths and Precision. The complete list of BIFs is in the RPGLE Built-in Functions Reference.

All examples are free-form RPGLE.

Numeric and conversion BIFs at a glance

BIFWhat it doesRounds?
%intConverts to a whole numberNo, truncates
%inthConverts to a whole numberYes, half adjust
%decConverts to packed decimal with the digits and decimals you chooseNo, truncates
%dechConverts to packed decimal with the digits and decimals you chooseYes, half adjust
%absAbsolute valueNot applicable
%remRemainder of a divisionNot applicable
%divInteger quotient of a divisionNo, truncates
%editcFormats a number as text with an edit codeNot applicable

%INT and %INTH

%int returns the whole-number part of a value and discards the decimals. %inth rounds half away from zero instead.

%int(expression)
%inth(expression)

The expression can be numeric or character data that holds a number. Character data that is not a valid number stops the program (status 00105).

dcl-s whole int(10);

whole = %int(3.9);        // 3
whole = %int(-3.9);       // -3
whole = %inth(3.5);       // 4
whole = %inth(-3.5);      // -4
whole = %int('42');       // 42, from character data

%DEC and %DECH

%dec returns a packed decimal value with the number of digits and decimal places you specify. %dech is the same function with half-adjust rounding.

%dec(expression : digits : decimals)
%dech(expression : digits : decimals)
ParameterMeaning
expressionThe value to convert. Numeric or character data
digitsTotal number of digits in the result. Optional for %dec, required for %dech
decimalsNumber of decimal places in the result. Optional for %dec, required for %dech
dcl-s price packed(7 : 2);

price = %dec(3.456 : 5 : 1);       // 3.4, truncated
price = %dech(3.456 : 5 : 1);      // 3.5, rounded
price = %dec('123.45' : 7 : 2);    // 123.45, from character data

%ABS

Returns the absolute value of a number.

%abs(expression)
dcl-s variance packed(9 : 2);

variance = %abs(-125.50);         // 125.50

%REM and %DIV

%rem returns the remainder of a division and %div returns the integer quotient. Both operands must have no decimal positions.

%rem(dividend : divisor)
%div(dividend : divisor)
dcl-s r int(10);
dcl-s q int(10);

r = %rem(7 : 3);      // 1
q = %div(7 : 3);      // 2
r = %rem(-7 : 3);     // -1
q = %div(-7 : 3);     // -2

The sign of %rem follows the first operand, and %div truncates toward zero. For any pair of operands, dividend = %div(dividend : divisor) * divisor + %rem(dividend : divisor).

%EDITC

Formats a number as character data, using an edit code.

%editc(number : edit-code {: *astfill | *cursym | currency-symbol})

The number is formatted using its declared decimal places.

Edit codeResult for 1234.5 in packed(9 : 2)Result for -1234.5
11,234.501,234.50
31234.501234.50
J1,234.501,234.50-

Code 1 and 3 print no sign. Code J prints a trailing minus sign for a negative number. Check the full edit code table in IBM’s ILE RPG reference for the other codes.

dcl-s amount packed(9 : 2) inz(1234.5);
dcl-s shown varchar(20);

shown = %trim(%editc(amount : 'J'));  // '1,234.50'

Worked example: invoice line total

Rounding at the right step matters. This example computes a line total, rounds it to cents, and shows the difference from truncating.

dcl-s qty    packed(5 : 0) inz(3);
dcl-s price  packed(7 : 3) inz(19.995);
dcl-s raw    packed(11 : 3);
dcl-s cents  packed(9 : 2);

raw   = qty * price;                  // 59.985
cents = %dech(raw : 9 : 2);           // 59.99, rounded half away from zero
cents = %dec(raw : 9 : 2);            // 59.98, truncated

Both results are correct for what they do. The business rule decides which one you need, so write it into the code with the BIF name rather than relying on an assignment’s default.

Overflow and size

Every conversion has a target size. %dec returns exactly the digits you request, and an assignment to a field that is too small can lose or reject digits. When the value may be large, check the range first, or declare the target as int(20) or packed(15 : 2).

Converting character data safely

Input from a screen, a file or a web service arrives as text. %int and %dec stop the program when the text is not a valid number, so test it first. For a whole number, %check against the digits tells you whether every character is allowed.

dcl-s input varchar(10) inz('12345');
dcl-s value int(10);

if %len(input) > 0 and %check('0123456789' : input) = 0;
  value = %int(input);
else;
  value = 0;      // reject or default, according to the business rule
endif;

This check accepts digits only. If the input can hold a sign, a decimal point or spaces, trim it and extend the allowed list, or validate in the caller before the value reaches this code.

Choosing between conversion BIFs

  • Use %int or %inth when the result is a count, an index or another whole number.
  • Use %dec or %dech when the result has decimal places, such as money, and you need to say how many digits and decimals it holds.
  • Use %inth and %dech when the business rule is to round, and %int and %dec when it is to truncate. Name the rule in a comment.
  • Use %rem and %div together when you need both parts of a division, for example pages and leftover lines.
  • Use %editc only for display. Keep numbers numeric until the last step.

Legacy opcodes

Fixed-format code did arithmetic and conversion with opcodes. They still compile; use expressions and BIFs in new code.

Fixed-format opcodeFree-form equivalent
Z-ADD=
ADD, SUB, MULT, DIV+, -, *, /
MVR%rem

Common mistakes

  • Using %int where a rounded value is needed, so 3.9 becomes 3.
  • Expecting %rem to return a positive value for a negative dividend.
  • Dividing by a variable that can be 0.
  • Converting to fewer digits than the value needs, which stops the program.
  • Concatenating %editc output without %trim, which leaves leading blanks in the message.

FAQ

How do I round a number in RPGLE?

Use %inth for a whole number or %dech for a number with decimals. Both round half away from zero. Alternatively, use the EVAL(H) operation, which half-adjusts the assignment.

How do I convert character data to a number?

Use %int for a whole number or %dec with digits and decimals for a value that has a decimal part. The character data must hold a valid number, or the program stops with a run-time error.

What is the difference between %REM and %DIV?

%div is the whole-number quotient and %rem is what is left over. Together they reproduce the original dividend.

Summary

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top