ZetCode

Algol 68 big integers

last modified November 14, 2026

An INT in Algol 68 Genie is a 32-bit signed integer, so the largest value it holds is 2147483647. Factorials, powers, and counts of combinatorial objects pass that limit quickly. The language answers with the long modes: LONG INT, LONG LONG INT, and longer modes still, whose precision is chosen by the program.

This article shows where an ordinary integer stops, how a LONG LONG INT is declared and printed, how the PR precision=... PR pragma gives the long modes hundreds of digits, and how to compute 100 factorial in full.

The limit of an INT

max int is the largest value of the mode INT. One more than that value cannot be represented, and the interpreter reports an arithmetic overflow instead of wrapping around to a negative number.

overflow.a68
BEGIN
  print(("max int = ", whole(max int, 0), newline));
  INT n := max int;
  print(("one more = ", whole(n + 1, 0), newline))
END

The first line prints, and the second raises INT math error (numerical result out of range). The running program stops at that point with exit status 1; the statements after the failing expression never run. Above the message the interpreter prints the offending source line and a caret under the expression, which the transcript below leaves out.

$ a68g overflow.a68
max int = 2147483647
a68g: runtime error: 1: INT math error (numerical result out of range) (detected in [] "SIMPLOUT" collateral-clause starting at "(" in this line).

Long long integers

A LONG LONG INT is a value of a different mode, not a wider INT variable. Arithmetic between the two modes is allowed through the widening coercion, but a long result cannot be narrowed back to an INT or a REAL. The conversion in the other direction is written LONG LONG INT(i).

long.a68
BEGIN
  LONG LONG INT f := 1;
  FOR i TO 25 DO f *:= LONG LONG INT(i) OD;
  print(("25!   = ", whole(f, 0), newline));
  print(("2^100 = ", whole(LONG LONG INT(2) ** 100, 0), newline));
  print(("fits in INT: ", f < LONG LONG INT(max int), newline))
END

The loop multiplies by a converted loop counter, because *:= between a long integer and an INT is not declared; the ordinary * does accept the mixture through widening. The comparison shows that 25 factorial is far beyond max int. The values are printed with whole(..., 0), because the default field of a long integer is very wide and would bury the digits in spaces.

$ a68g long.a68
25!   = 15511210043330985984000000
2^100 = 1267650600228229401496703205376
fits in INT: F

Setting the precision

The number of significant digits of the long modes is set by a pragma at the top of the program: PR precision=200 PR. The default in this build is 70 digits, which holds 53 factorial but not 100 factorial, whose 158 digits need a larger precision.

factorial100.a68
PR precision=200 PR
BEGIN
  LONG LONG INT f := 1;
  FOR i TO 100 DO f *:= LONG LONG INT(i) OD;
  print(("100! = ", whole(f, 0), newline));
  print(("digits: ", whole(UPB whole(f, 0), 0), newline))
END

The pragma precedes the block, so every long value in the program is created with the new precision. The result is exact, including the long run of trailing zeros that comes from the factors of 2 and 5. The upper bound of the string returned by whole is the number of digits, which is 158.

$ a68g factorial100.a68
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
digits: 158

Fibonacci numbers in long modes

The iterative Fibonacci procedure needs only two long integers, and it reaches values that an INT overflowed long before. The 200th Fibonacci number has 42 digits, so a precision of 100 leaves room for the intermediate sums as well.

fib200.a68
PR precision=100 PR
BEGIN
  LONG LONG INT a := 0, b := 1;
  FOR i TO 200 DO
    LONG LONG INT t := a + b;
    a := b;
    b := t
  OD;
  print(("fib(200) = ", whole(a, 0), newline))
END

After each step a holds the previous number and b the current one, so after 200 steps a is the 200th Fibonacci number when the sequence starts at 0. The temporary t is necessary because the assignment to a would otherwise destroy the value needed by b.

$ a68g fib200.a68
fib(200) = 280571172992510140037611932413038677189525

The --precision option

A program that does not contain the pragma uses the precision given on the command line. This program computes 100 factorial and prints only the number of digits and the first twenty of them, which keeps the output short.

fact100.a68
BEGIN
  LONG LONG INT f := 1;
  FOR i TO 100 DO f *:= LONG LONG INT(i) OD;
  STRING s = whole(f, 0);
  print((whole(UPB s, 0), " digits, starts with ", s[1:20], newline))
END

Run without options, the program stops with a long integer overflow, because the default precision is too small for the intermediate product. --precision 200 raises the limit before the program is elaborated, and the same file then succeeds. A pragma in the source takes precedence over the option, so publishing a program with its precision in the source makes the result independent of the command line.

$ a68g fact100.a68
a68g: runtime error: 1: LONG LONG INT value out of bounds (numerical result out of range) (detected in VOID loop-clause starting at "FOR" in this line).
$ a68g --precision 200 fact100.a68
158 digits, starts with 93326215443944152681

Division, remainder, and comparisons

Long integers support the same operators as INT: OVER for integer division, MOD for the remainder, ** for a power, and the usual comparisons. A comparison between a long integer and an INT widens the short operand, so no explicit conversion is needed.

mixed.a68
BEGIN
  LONG LONG INT n := 1;
  FOR i TO 30 DO n *:= 2 OD;
  print(("n       = ", whole(n, 0), newline));
  print(("n over 3 = ", whole(n OVER 3, 0), newline));
  print(("n mod 7  = ", whole(n MOD 7, 0), newline));
  print(("n > 10^9 = ", n > 1000000000, newline))
END

The value is 2 to the 30th, which still fits in an INT, but it is kept in a long variable throughout. Division truncates towards zero, the remainder is 1, and the comparison yields T, the way a BOOL prints. A boolean result can be used directly in an IF or stored in a variable of mode BOOL.

$ a68g mixed.a68
n       = 1073741824
n over 3 = 357913941
n mod 7  = 1
n > 10^9 = T

Next steps

The number formatting article shows how to print these values in columns, and the operators article explains the priorities of the arithmetic used here. The error handling article describes what a program can do when a runtime check such as an overflow fails.

Source

Revised Report on the Algorithmic Language Algol 68

The Algol 68 Genie project

In this article we have seen the limit of an INT, declared long integers, raised their precision with a pragma and with a command-line option, and computed 100 factorial and the 200th Fibonacci number exactly.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Algol 68 tutorials.