2.1.3 ⁂Arithmetic
TeX count registers only allow integer values.
Even the registers that store dimensions (such as \parindent
)
use integer arithmetic as TeX internally stores lengths in terms
of its sp unit ( 65536 sp =
1 pt). There are, however, some packages that allow you
to perform decimal calculations using TeX (see, for example,
the calculation topic or the arithmetic topic).
However, first let's look at just integer arithmetic, as that can be performed more efficiently using TeX primitive that using LaTeX packages. TeX count registers are defined using:
This not only allocates a new register, but also assigns a control sequence ⟨register cs⟩ that can be used to reference the register. For example:
\newcount\mycount
allocates a new register that can be referenced using \mycount
.
\newcount
with LaTeX's
\newcounter
command. With the LaTeX version, you provide
a label as the argument. Internally, \newcounter
uses
\newcount
to create a register where the control sequence is
formed from \c@
⟨label⟩ (where ⟨label⟩ is the
argument of \newcounter
). However, \newcounter
performs more than simply assigning a new register. It also provides
a command that can be used to format the value of the register
(\the
⟨label⟩), allows the value to be
cross-referenced using LaTeX's \label
/\ref
(along
with \refstepcounter
), and can also automatically reset the
value of the register when another counter is incremented. If I only
want a scratch variable to calculate integer values, I'll just
define a register using \newcount
, as it helps to reduce the
clutter of (possibly already complicated code) if I can refer to the
register control sequence directly, without the cumbersome use of
\value
or internal commands. (See, for example, the
\julianday
register in Example 38.)
A register can be assigned a value using the syntax:
For example:
\mycount = 25
sets the value of the \mycount
register to 25.
Note that it's sometimes necessary to use \relax
after the
assignment to prevent TeX from prematurely expanding the following
token. eTeX provides a primitive for evaluating expressions:
For example:
\mycount=\numexpr(25+5)/3
It's usually a good idea to put \relax
after ⟨integer expression⟩
in case it happens to be followed by something that could be interpreted as
part of the expression:
There is a similar eTeX primitive for evaluating dimension expressions:
You can display the value of the register using:
For example:
produces:
This also works with other types of registers. For example:
produces:
There's a similar TeX primitive that works on either a register or a number (either typed explicitly or stored in a macro):
For example:
\mycount = 25 \newcommand{\mynum}{40}% Register: \number\mycount. Macro: \number\mynum. Number: \number46.
Produces:
The contents of a register can be incremented using:
where ⟨value⟩ may be another register, a macro that expands to a value or a plain number. The by keyword is optional. For example:
produces:
The contents of a register can be multiplied by a value using:
As with \advance
, the keyword by may be omitted.
For example:
produces:
The contents of a register can be divided by a value using:
As before the by keyword may be omitted. Remember that this uses integer arithmetic. For example:
produces:
For decimal arithmetic, there are a number of packages available, such as fp [57] and pgfmath [102]. In addition, the LaTeX3 experimental bundle [50] also provides decimal arithmetic. [LaTeX3 programming] However, it uses LaTeX3 syntax, which is beyond the scope of this book.
The datatool package provides
an interface to either fp or pgfmath. The default is to
use fp but you can change this using the
math=pgfmath
package option:
\usepackage[math=pgfmath]{datatool}
The pgfmath package is part of the pgf bundle, so if you intend loading pgf (or tikz) in your document, it's more efficient to use the pgfmath engine with datatool to avoid the overhead of loading an additional package.
The fp and pgfmath packages use very different syntax to perform the same calculations, but datatool provides the same interface commands regardless of the underlying arithmetical package, so you can switch engines without having to change your code, however you may find minor differences in the results, caused by different levels of precision or rounding.
There are two types of arithmetical commands provided by datatool: those that operate on raw plain numbers that use a full stop as the decimal point with no group separator, and those that operate on locale dependent numbers or currency. The first type are prefixed by dtl. For example:
This rounds ⟨number⟩ to ⟨num digits⟩ decimal places and stores the result in the control sequence ⟨cs⟩.
The second type are prefixed by DTL. For example:
which is the locale-dependent alternative to \dtlround
.
The plain versions (prefixed with dtl) all perform local
assignments. If you need a global assignment you can use
\global
\let
on the result (see
§2.1.1 Macro Definitions). For example:
The locale versions (prefixed with DTL) come with two alternatives: a local version and a global version. The global versions have the prefix DTLg such as:
which is the global alternative to \DTLround
.
For the locale versions, the decimal character defaults to a full stop and the number group separator defaults to a comma, but these can be changed using:
where ⟨number group char⟩ is the number group separator and ⟨decimal char⟩ is the decimal character. For example, to switch to commas for the decimal character and a full stop for the number group separator:
Now, any numbers that use this format need to use the control sequences prefixed with DTL instead of dtl:
This produces:
Example (plain numbers):
produces:
Example (locale numbers):
produces:
The locale version \DTLround
first converts the formatted
number into a plain number, performs the arithmetical operation, and
then converts the result back into a formatted number. Therefore, if
your numbers are all plain numbers, it's more efficient to use
\dtlround
instead of \DTLround
. Similarly for all the commands
described below.
Addition can be performed using:
for the plain version, or
for the scoped locale version, or
for the global locale version. In each case the sum of ⟨number 1⟩ and ⟨number 2⟩ is stored in the control sequence ⟨cs⟩.
Subtraction can be performed using:
for the plain version, or
for the scoped locale version, or
for the global locale version. In each case ⟨number 1⟩ minus ⟨number 2⟩ is stored in the control sequence ⟨cs⟩.
Multiplication can be performed using:
for the plain version, or
for the scoped locale version, or
for the global locale version. In each case the product of ⟨number 1⟩ and ⟨number 2⟩ is stored in the control sequence ⟨cs⟩.
Division can be performed using:
for the plain version, or
for the scoped locale version, or
for the global locale version. In each case ⟨number 1⟩ divided by ⟨number 2⟩ is stored in the control sequence ⟨cs⟩.
The absolute value can be obtained using:
for the plain version, or
for the scoped locale version, or
for the global locale version. In each case the absolute value of ⟨number⟩ is stored in the control sequence ⟨cs⟩.
The negation can be obtained using:
for the plain version, or
for the scoped locale version, or
for the global locale version. In each case the negative of ⟨number⟩ is stored in the control sequence ⟨cs⟩.
There are also commands available to perform arithmetic operations on a column of data stored in one of datatool's internal database. However, these use the DTL versions and since TeX isn't designed for data management, it's better to perform these calculations in your spreadsheet or when you pull the data from a SQL database.
This book is also available as A4 PDF or 12.8cm x 9.6cm PDF or paperback (ISBN 978-1-909440-07-4).