Beginner

Operators in ABAP

Master arithmetic, comparison, logical, and string operators in ABAP - including business-focused features like the &&-concatenation, IS INITIAL, and string templates.

Operators are the building blocks of every ABAP expression - from calculating an order total in SAP S/4HANA to comparing posting dates in a financial report. Because ABAP was designed for business applications, it offers two parallel sets of comparison operators (symbolic like = and word-style like EQ), an explicit integer-division operator (DIV), and a chainable string-concatenation operator (&&) that is unusually safe with trailing blanks.

ABAP is a statically and strongly typed multi-paradigm language. Numeric operators automatically widen to the largest operand type, so mixing an integer (i) and a packed decimal (p) produces a packed result - a feature that was practically required for currency arithmetic in SAP R/3. Modern ABAP (7.40+) added string templates with embedded expressions, dramatically reducing the verbosity of formatted output.

In this tutorial you will see arithmetic, comparison, logical, string, and assignment operators - plus ABAP’s special “is” predicates such as IS INITIAL - all running on Node.js via the open-abap transpiler.

A Single Comprehensive Example

We will use one program that exercises every operator family. Because the open-abap Docker pipeline copies hello.abap into the project as the report source, we keep the same filename convention here.

Create a file named hello.abap:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
REPORT zhello.

" -------- Arithmetic operators --------
DATA: lv_a TYPE i VALUE 17,
      lv_b TYPE i VALUE 4,
      lv_r TYPE i.

lv_r = lv_a + lv_b.
WRITE: / |17 +   4 = { lv_r }|.

lv_r = lv_a - lv_b.
WRITE: / |17 -   4 = { lv_r }|.

lv_r = lv_a * lv_b.
WRITE: / |17 *   4 = { lv_r }|.

lv_r = lv_a DIV lv_b.
WRITE: / |17 DIV 4 = { lv_r }|.

lv_r = lv_a MOD lv_b.
WRITE: / |17 MOD 4 = { lv_r }|.

lv_r = lv_a ** 2.
WRITE: / |17 **  2 = { lv_r }|.

" -------- Compound assignment --------
DATA: lv_counter TYPE i VALUE 10.
lv_counter = lv_counter + 5.
WRITE: / |counter after + 5: { lv_counter }|.

" -------- Comparison operators --------
" ABAP supports both symbolic and word forms.
IF lv_a > lv_b.
  WRITE: / 'a > b is true (symbolic form)'.
ENDIF.

IF lv_a GT lv_b.
  WRITE: / 'a GT b is true (word form)'.
ENDIF.

IF lv_a <> lv_b.
  WRITE: / 'a <> b is true'.
ENDIF.

IF lv_a EQ 17.
  WRITE: / 'a EQ 17 is true'.
ENDIF.

" -------- Logical operators --------
IF lv_a > 10 AND lv_b < 10.
  WRITE: / 'AND: both conditions hold'.
ENDIF.

IF lv_a < 0 OR lv_b > 0.
  WRITE: / 'OR: at least one condition holds'.
ENDIF.

IF NOT lv_a = 0.
  WRITE: / 'NOT: a is not zero'.
ENDIF.

" -------- String concatenation --------
DATA: lv_left  TYPE string VALUE 'Hello',
      lv_right TYPE string VALUE 'ABAP',
      lv_msg   TYPE string.

" The && operator concatenates without preserving trailing blanks.
lv_msg = lv_left && ', ' && lv_right && '!'.
WRITE: / lv_msg.

" -------- String templates (ABAP 7.40+) --------
DATA(lv_name)  = 'World'.
DATA(lv_hello) = |Welcome, { lv_name }!|.
WRITE: / lv_hello.

" -------- IS INITIAL predicate --------
" 'Initial' means the type-default value (empty string, 0, etc.).
DATA lv_empty TYPE string.
IF lv_empty IS INITIAL.
  WRITE: / 'lv_empty IS INITIAL'.
ENDIF.

DATA lv_zero TYPE i.
IF lv_zero IS INITIAL.
  WRITE: / 'lv_zero IS INITIAL (value 0)'.
ENDIF.

" -------- Operator precedence --------
" ** binds tighter than * /, which bind tighter than + -.
" Parentheses must have spaces around them in ABAP.
DATA lv_calc TYPE i.
lv_calc = ( 2 + 3 ) * 4.
WRITE: / |( 2 + 3 ) * 4 = { lv_calc }|.

lv_calc = 2 + 3 * 4.
WRITE: / |2 + 3 * 4   = { lv_calc }|.

Notes on the Code

Arithmetic: / versus DIV

ABAP distinguishes real division from integer division:

  • / performs real division. When the result is assigned to an integer field, ABAP rounds (commercial rounding) - so 17 / 4 would store 4 in lv_r.
  • DIV truncates toward zero, giving the integer quotient directly: 17 DIV 4 = 4.
  • MOD returns the remainder: 17 MOD 4 = 1.

For currency math you would normally use the packed type p DECIMALS n, which preserves cents exactly.

Symbolic vs. word-style comparisons

ABAP exposes two equivalent vocabularies, a holdover from its COBOL-influenced early years. Both compile to the same operation:

SymbolicWordMeaning
=EQequal
<>NEnot equal
<LTless than
>GTgreater than
<=LEless or equal
>=GEgreater or equal

Style guides at most SAP shops prefer the symbolic forms in modern code.

&& versus the older &

The && operator (added in ABAP 7.02) concatenates strings while ignoring trailing blanks of fixed-length character fields. Older code uses & inside a single CONCATENATE ... INTO ... statement, which behaves differently and requires RESPECTING BLANKS to keep padding.

IS INITIAL

Rather than comparing against a sentinel, ABAP exposes the predicate IS INITIAL, which is true when the variable holds the type-default value: '' for strings, 0 for numerics, 00000000 for dates, an empty internal table, and so on. The complement is IS NOT INITIAL.

Parentheses need spaces

ABAP’s parser requires whitespace around ( and ) when they group sub-expressions: ( 2 + 3 ) * 4 is valid, (2 + 3) * 4 is not. This trips up newcomers from C-family languages.

Running with Docker

1
2
3
4
5
# Pull the Node.js image
docker pull node:20

# Transpile and run hello.abap via the open-abap toolchain
docker run --rm -v $(pwd):/work node:20 sh -c 'cd /work && mkdir -p abap_project/src && cd abap_project && npm init -y >/dev/null 2>&1 && npm install --silent @abaplint/transpiler-cli @abaplint/runtime 2>/dev/null && echo "{\"input_folder\":\"src\",\"output_folder\":\"output\",\"write_unit_tests\":false,\"options\":{\"ignoreSyntaxCheck\":true}}" > abap_transpile.json && echo "{\"global\":{\"files\":\"/src/**/*.*\"},\"syntax\":{\"version\":\"v702\",\"errorNamespace\":\".\"}}" > abaplint.json && cp /work/hello.abap src/zhello.prog.abap && echo "<?xml version=\"1.0\"?><abapGit version=\"v1.0.0\"><asx:abap xmlns:asx=\"http://www.sap.com/abapxml\"><asx:values><PROGDIR><NAME>ZHELLO</NAME><SUBC>1</SUBC></PROGDIR></asx:values></asx:abap></abapGit>" > src/zhello.prog.xml && ./node_modules/.bin/abap_transpile >/dev/null && echo "import runtime from \"@abaplint/runtime\";globalThis.abap = new runtime.ABAP();await import(\"./output/zhello.prog.mjs\");" > run.mjs && node run.mjs && cd /work && rm -rf abap_project'

The pipeline:

  1. Mounts the current directory at /work.
  2. Creates a temporary npm project and installs @abaplint/transpiler-cli plus @abaplint/runtime.
  3. Stages hello.abap as src/zhello.prog.abap with the abapGit XML metadata that the transpiler expects.
  4. Transpiles ABAP to ES modules under output/.
  5. Boots the ABAP runtime in Node.js and dynamically imports the compiled program.

Expected Output

17 +   4 = 21
17 -   4 = 13
17 *   4 = 68
17 DIV 4 = 4
17 MOD 4 = 1
17 **  2 = 289
counter after + 5: 15
a > b is true (symbolic form)
a GT b is true (word form)
a <> b is true
a EQ 17 is true
AND: both conditions hold
OR: at least one condition holds
NOT: a is not zero
Hello, ABAP!
Welcome, World!
lv_empty IS INITIAL
lv_zero IS INITIAL (value 0)
( 2 + 3 ) * 4 = 20
2 + 3 * 4   = 14

Key Concepts

  • Two comparison vocabularies: symbolic (=, <>, <) and word-form (EQ, NE, LT) are interchangeable - prefer symbolic in modern code.
  • / rounds, DIV truncates: real division assigned to an integer field is rounded; use DIV for explicit integer division and MOD for the remainder.
  • ** is exponentiation: ABAP uses double-asterisk for power, not ^.
  • && concatenates strings without surprises around trailing blanks; older code uses CONCATENATE ... INTO.
  • String templates |text { expr }| (ABAP 7.40+) embed expressions inline and replace most uses of CONCATENATE for formatted output.
  • IS INITIAL is the idiomatic ABAP test for “default value” - cleaner than comparing against '' or 0.
  • Logical operators are word-form only: AND, OR, NOT - there is no && or || for booleans (those symbols are reserved for strings).
  • Parentheses need surrounding spaces: ( 2 + 3 ) * 4 is the only valid spelling - a parser quirk inherited from ABAP’s report-language origins.

Running Today

All examples can be run using Docker:

docker pull node:20
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining