TeX does not include any ‘native’ support for floating point calculations, but that has not stopped lots of (La)TeX users wanting to do sums (and more complicated things) in their document. As TeX is Turing complete, it’s not a surprise that there are several ways to implement calculations. For end users, the differences between these are not important: what is key is what to use. Here, I’ll give a bit of background, look at the various possibilities, then move on to give a recommendation.
Background
When Knuth wrote TeX, he had one aim in mind: high-quality typesetting. He also wanted to have sources which were truly portable between different systems. At the time, there was no standard for specifying how floating point operations should be handled at the hardware level: as such, no floating point operations were system-independent.
Knuth decided that TeX would provide no user access to anything dependent on platform-specific floating-point operations. That means that the TeX functions that look like floats (in particular dimen work) actually use integer arithmetic and convert ‘at the last minute’.
Technical considerations
There are two basic approaches to setting up floating point systems in TeX: either use dimensions or doing everything in integer arithmetic.
Using dimensions, the input range is limited and the output has restricted accuracy. But on the other hand, many calculations are quite short and they are fast. On the other hand, if everything is coded in integer arithmetic, the programmer can control the accuracy completely, at the cost of speed.
Although it’s not an absolute requirement, e-TeX does make doing things a bit easier: rather than having to shuffle everything a piece at a time, it is possible to use inline expressions for quite a lot of the work.
Another key technical aspect is expandability. This is useful for some aspects of TeX work, particularly anywhere that it ‘expects a number’: only expansion is allowed in such places.
One other thing to consider is handling of TeX registers as numbers. Converting
for example a length into something that can be used in a floating point
calculation is handy, and it matches what e-TeX does in for example \numexpr
.
But in macro code it has to be programmed in.
Functionality
The other thing to think about here is functionality: what is and isn’t needed in terms of mathematics. Doing straight-forward arithmetic is obviously easier than working out trigonometry, logarithms, etc. What exactly you need depends on the use case, but obviously more functionality is always better.
(Package) options
For simple work using the dimen approach is convenient and fast: it takes
only a small amount of work to set up stripping off the pt
part. I’m writing
here for people who don’t want to delve into TeX innards, so let’s assume
a pre-packaged solution is what is required.
There are lots of possible solutions on CTAN which cover some or all of the above. I don’t want to get into a ‘big list’, so I’ll simply note here that the following are available:
Some of these have variable or arbitrary precision, others work to a pre-determined level, and they also vary in terms of functions covered, expandability and so on.
I want to focus in on three possible ‘contenders’:
fp
, pgf
and the LaTeX3 FPU. The fp
package formally
uses fixed not floating point code, but the key for us here is that it
allows a wide range of high-precision calculations. It’s also been
around for a long time. However, it’s quite slow and doesn’t have convenient
expression parsing (it does reverse Polish).
On the flip side, the mathematics engine in pgf
uses dimens internally, so
it is (relatively) fast but is limited in accuracy. The range limits also
show up in some unexpected places, as a lot of range reduction is needed to make
everything work. On the other hand, \pgfmathparse
does read ‘normal’
mathematical expressions, so it’s pretty easy to use.
The LaTeX3 FPU is part of expl3
, but is
available nowadays as a document-level package
xfp
. In contrast to both fp
and the pgf
approach, the LaTeX3 FPU is expandable. Like pgf
, using the FPU means
we can use expressions, and we also get reasonable
performance (Bruno Le Floch worked
hard on this aspect). The other thing to note is that the FPU is intended to
match behaviour specified in the decimal IEEE
754 standard, and that the team have
a set of tests to try to make sure things work as expected.
There’s one other option that one must consider: Lua. If you address only using LuaTeX, you can happily break out into Lua and use its ability to use the ‘real’ floating point capabilities of a modern PC. The one wrinkle is that without a bit of work, the Lua code doesn’t know about TeX material: registers and so on need to be pre-processed. It also goes without saying that using Lua means being tied to LuaTeX!
Recommendation
As you can see above, there are several options. However, for end users wanting to do calculations in documents I think there is a clear best choice: the LaTeX3 FPU.
\documentclass{article}
\usepackage{xfp}
\begin{document}
\fpeval{round(sqrt(2) * sind(40),2)}
\end{document}
You’d probably expect me to say that: I am on the LaTeX
team. But that’s not the reason. Instead,
it’s that the FPU is almost as fast as using dimens (see pgf
benchmarking),
but offers the same accuracy as a typical GUI application for maths. It also
integrates into normal LaTeX conventions with no user effort.