Operators in ALGOL 60
Learn arithmetic, relational, and logical operators in ALGOL 60, including the language’s distinctive operator set, precedence rules, and Boolean expressions
Introduction
Operators are the verbs of an expression — the symbols that combine values into computations. ALGOL 60 set the template that nearly every later imperative language followed: separate operator categories for arithmetic, relations, and Boolean logic, each with its own precedence level. When you write a * b + c in Python, C, or Java, the rule that multiplication binds tighter than addition was effectively codified by the ALGOL 60 Report.
What makes ALGOL 60’s operators interesting today is the things modern languages quietly dropped. ALGOL 60 distinguishes integer division from real division using two different symbols. It has a built-in exponentiation operator. It treats Boolean as a first-class type with implication and equivalence operators — ⊃ and ≡ in the Report, written impl and eqv in GNU MARST. And assignment is a deliberate :=, not an overloaded =, leaving = free to mean what it does in mathematics: equality.
Because ALGOL 60 is statically and strongly typed, operator behaviour follows the operand types. Mixing integer and real in an arithmetic expression promotes the result to real. The original Report used special mathematical glyphs (↑, ≤, ≠, ∧, ∨, ¬) that few keyboards could produce; GNU MARST uses ASCII spellings instead, which is what we’ll write below.
Arithmetic Operators
ALGOL 60 provides the standard arithmetic operators plus a few distinctive ones. Create a file named operators.alg:
begin
integer a, b, q, r, p;
real x, y, z;
a := 17;
b := 5;
comment ALGOL 60 has two different division operators;
x := a / b; comment real division, result is 3.4;
q := a div b; comment integer division, result is 3;
r := a - (a div b) * b; comment remainder, computed manually, result is 2;
comment Exponentiation uses ** in MARST;
p := 2 ** 10; comment 1024;
comment Mixed integer and real promotes to real;
y := 7 + 2.5; comment result is 9.5;
z := -y; comment unary minus, result is -9.5;
outstring(1, "a / b = "); outreal(1, x); outstring(1, "\n");
outstring(1, "a div b = "); outinteger(1, q); outstring(1, "\n");
outstring(1, "a mod b = "); outinteger(1, r); outstring(1, "\n");
outstring(1, "2 ** 10 = "); outinteger(1, p); outstring(1, "\n");
outstring(1, "7 + 2.5 = "); outreal(1, y); outstring(1, "\n");
outstring(1, "-y = "); outreal(1, z); outstring(1, "\n")
end
A few things to notice:
/is always real division. Even when both operands are integers,/yields arealresult. This is the opposite of C and Java, where/between two integers truncates.divis integer division. It requires integer operands and produces an integer. The Report wrote this as÷.- No
modoperator. ALGOL 60 has no built-in remainder operator. You compute remainders explicitly asa - (a div b) * b. **is exponentiation. The Report’s↑becomes**in MARST. It accepts integer or real bases and exponents.- Unary minus works as expected on numeric values.
Relational and Boolean Operators
Relational operators compare values and produce a Boolean result. ALGOL 60 then combines Booleans using logical operators that include two that most modern languages omit: implication and equivalence. Create a file named boolean_ops.alg:
begin
integer m, n;
Boolean p, q, r;
m := 7;
n := 12;
comment Relational operators produce Boolean values;
p := m < n; comment true;
q := m = n; comment false (note: = is equality, not assignment);
r := m >= 7; comment true;
outstring(1, "m < n : "); if p then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
outstring(1, "m = n : "); if q then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
outstring(1, "m >= 7 : "); if r then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
comment Logical operators: not, and, or, impl (implies), eqv (equivalent);
outstring(1, "p and r : ");
if p and r then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
outstring(1, "q or r : ");
if q or r then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
outstring(1, "not q : ");
if not q then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
comment p impl q is equivalent to (not p) or q;
outstring(1, "p impl q : ");
if p impl q then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n");
comment p eqv q is true when p and q have the same Boolean value;
outstring(1, "p eqv r : ");
if p eqv r then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n")
end
The full relational set is <, <=, =, >=, >, != (Report glyphs: <, ≤, =, ≥, >, ≠). Use = for equality comparison — assignment is :=, so there is no ambiguity.
The Boolean operators in order of precedence (loosest to tightest, the reverse of typical reading order) are: eqv, impl, or, and, not. impl and eqv are heirlooms of ALGOL 60’s mathematical heritage: p impl q means “if p then q” and equals (not p) or q; p eqv q is true exactly when p and q agree.
Operator Precedence and Assignment
Precedence determines how an expression is parsed when parentheses are absent. ALGOL 60’s precedence order, from highest to lowest, is:
**(exponentiation)*,/,div+,-(binary and unary)<,<=,=,>=,>,!=notandorimpleqv
Create a file named precedence.alg:
begin
integer result1, result2, result3;
Boolean t;
comment 2 + 3 * 4 parses as 2 + (3 * 4) = 14, not (2 + 3) * 4 = 20;
result1 := 2 + 3 * 4;
comment Parentheses force a different grouping;
result2 := (2 + 3) * 4;
comment ** binds tighter than unary minus: -2 ** 2 is -(2 ** 2) = -4;
result3 := -2 ** 2;
outstring(1, "2 + 3 * 4 = "); outinteger(1, result1); outstring(1, "\n");
outstring(1, "(2+3) * 4 = "); outinteger(1, result2); outstring(1, "\n");
outstring(1, "-2 ** 2 = "); outinteger(1, result3); outstring(1, "\n");
comment Assignment with := not =;
comment Multiple targets are allowed: a := b := expr;
begin
integer a, b;
a := b := 99;
outstring(1, "a, b after a := b := 99 -> ");
outinteger(1, a); outstring(1, ", "); outinteger(1, b); outstring(1, "\n")
end;
comment Boolean precedence: and binds tighter than or;
t := true or false and false;
outstring(1, "true or false and false = ");
if t then outstring(1, "true") else outstring(1, "false");
outstring(1, "\n")
end
Two things deserve emphasis. First, assignment in ALGOL 60 is a statement, not an expression — you cannot embed a := 5 inside a larger expression the way you can in C. But ALGOL 60 does permit multiple targets on the left, so a := b := 99 assigns 99 to both b and a. Second, the precedence list above means true or false and false is true or (false and false) which is true, not (true or false) and false which would be false.
Running with Docker
Pull the official image and run each example:
| |
Expected Output
Output of operators.alg:
a / b = +3.40000000000000E+000
a div b = +3
a mod b = +2
2 ** 10 = +1024
7 + 2.5 = +9.50000000000000E+000
-y = -9.50000000000000E+000
Output of boolean_ops.alg:
m < n : true
m = n : false
m >= 7 : true
p and r : true
q or r : true
not q : true
p impl q : false
p eqv r : true
Output of precedence.alg:
2 + 3 * 4 = +14
(2+3) * 4 = +20
-2 ** 2 = -4
a, b after a := b := 99 -> +99, +99
true or false and false = true
GNU MARST formats integers with an explicit sign and real numbers in scientific notation by default; that’s the outinteger/outreal library behaviour, not part of the operator itself.
Key Concepts
- Two division operators.
/always produces a real result;divis integer-to-integer division. There is no built-inmod— compute remainders asa - (a div b) * b. - Exponentiation is built in.
a ** b(the Report’s↑) is part of the language, not a library function, and binds tighter than multiplication. - Assignment is
:=, equality is=. Because the two are distinct, ALGOL 60 avoids the=vs==confusion that haunts C-family languages. - Boolean is a first-class type. Relational operators yield
Booleanvalues you can store, combine, and pass to procedures. implandeqvare unusual. Few modern languages include logical implication or equivalence as native operators; they survive in ALGOL 60 from its mathematical-logic heritage.- Precedence is explicit and well-defined. The hierarchy
** > *,/,div > +,- > relations > not > and > or > impl > eqvwas the model copied (with variations) by Pascal, Ada, and Modula. - Mixed-type arithmetic promotes to real. Combining an
integerand arealproduces areal; assigning a real to an integer requires the conversion to be explicit (or rounds, depending on context). - No short-circuit guarantees in the Report. Unlike C’s
&&and||, ALGOL 60’sandandorare not specified to short-circuit. Don’t rely on the right operand being skipped.
Running Today
All examples can be run using Docker:
docker pull codearchaeology/algol60:latest
Comments
Loading comments...
Leave a Comment