How to get maximum number that \newcount can hold?

While investigating a little I found out some interesting things (for me at least) and a way to get the maximum value of a count register. (This answer will use Knuth TeX, so no \numexpr or anything, but of course it works with e-TeX too.)

TeX uses signed 32-bit integers internally. In a signed 32-bit integer, numbers range from -231 and 231-1, and their order in increments of one is:

%                      sign change V
0, 1, ..., 2147483646, 2147483647, -2147483648, -2147483647, ..., -1

However TeX doesn't let you input a number larger than 231-1:

enter image description here

However if you store 231-1 in a \counter and \advance\counter by 1 you do get -231. As Frank says in the comment below and Karl in his answer, Knuth didn't add arithmetic overflow check to TeX's \advance for efficiency reasons. However this opens you to do some devious tricks :-)

You can exploit that to brute-force your way into finding out what the value of the maximum integer is. You can add one to a counter until its sign changes. When the sign changes, the previous value was the maximum integer. To make things faster you can start with larger steps, and reduce the step size until you find out which value is the maximum. The code below does that (pretty quickly):

\newcount\maxcount
\newcount\tmp

\def\gobble#1{}
\def\addloop#1{%
  \advance\maxcount by #1 % Add to the counter
  \ifnum\maxcount<\tmp % If it is negative
    \advance\maxcount by -#1 % undo
    \expandafter\gobble % and return
  \else
    \tmp\maxcount % otherwise save the value
    \expandafter\addloop % and try again
  \fi{#1}}
\def\getmaxcount{%
  \maxcount=0
  \tmp=0
  \addloop{1000000}% Faster
  \addloop{1000}% Slower
  \addloop{1}% Slowest
}

\getmaxcount
\showthe\maxcount

\bye

First we initialise two counters as zero, then we start by stepping the \maxcount counter by some value. If the stepped value makes \maxcount negative (i.e., it becomes smaller than \tmp), then we passed the sign-change boundary and need to backtrack. Otherwise, try again. We can start doing that for large values, so that it arrives to the limit faster, and then reduce the step to find out the exact match.

The terminal output for the code above is:

C:\Users\Phelype\tex.sx>tex test.tex
This is TeX, Version 3.14159265 (TeX Live 2019/W32TeX) (preloaded format=tex)
(./test.tex
> 2147483647.
l.25 \showthe\maxcount

?
 )
No pages of output.
Transcript written on test.log.

The maximum integer allowed in a TeX \count register is 2147483647.

You can access it as \number\numexpr2*\maxdimen+1\relax, if you use e-TeX extensions.


Frank is correct. In section 104 of tex.web is this text:

The present implementation of \TeX\ does not check for overflow when dimensions are added or subtracted. This could be done by ... but the chance of overflow is so remote that such tests do not seem worthwhile.

The same statement is on page 660 of Digital Typography, The Final Errors of TeX article.

I think Knuth has reiterated that point elsewhere also, perhaps in one of the tune-up reports, where the question was about crashing TeX with devious arithmetic, but I can't find that one now ...