# What is the most convenient way to do general-arithmetic calculations involving lengths?

I know LaTeX can store at least two types of numbers: Dimensionless quantities (i.e. 1, pi, etc.) and lengths (i.e. 1pt, \textwidth, etc.). Is there some convenient, general way to do calculations, using more or less complicated arithmetic expressions that can involve both dimensionless quantities and lengths?

For example, how can you most easily evaluate the expression 1/(1/a+1/b), where a and b are lengths, and store the result as a new length? Or how to calculate and store the hypotenuse of a right triangle, with a and b being the two shortest sides, squareroot(a^2+b^2)? And is it possible to calculate and store areas (e.g. a*b)?

Is there some easy way to do calculations like these straight away, or do you have to convert lengths to dimensionless quantities by dividing them with, say, 1pt (I just picked a reference length at random), before you can do that?

• You can look at tex.stackexchange.com/questions/67919/… and tex.stackexchange.com/questions/11346/…. You can use pgfmath, the calc package or the fp package. Tex is not a very fine tool to do complex calculations, the restrictions are big. May 3, 2013 at 14:17
• @Joseph, can you explain to me the rationale for not tagging this as LaTeX-specific? When searching the site for questions/answers on this topic for other TeX environments such as plain TeX or ConTeXt, there's currently no way to know from the title or tags that this question is specific to LaTeX. I thought that was the purpose of tags, to make search more effective. Maybe there's a better tag for that than latex-project? Or maybe, in your view, the question isn't specific to LaTeX? Strawberry, was that your intent? Sep 5, 2013 at 14:15
• @LarsH Two reasons. First as you say this is not fundamentally LaTeX-specific. You can use the fp and pgfmath packages with plain or ConTeXt, for example. Secondly, there is a 'LaTeX assumption' on the site as it's realistic: notice that most questions are about LaTeX but we don't have a latex tag. The latex-project tag is really aimed at things that are very 'focussed', for example LaTeX kernel mechanisms such as float handling. Notice that there are tags for the other formats, e.g. plain-tex. Sep 5, 2013 at 14:19
• @LarsH Also note that we have always had an understanding that it's acceptable to answer a format-specific question using a different format, provided you say so, Thus you'll see several answers saying 'In ConTeXt, you would tackle this by doing ...' where the MWE is LaTeX-focussed. Sep 5, 2013 at 14:21
• As for the intent of the question, I interpreted it as LaTeX-specific, though I'm now less sure. Perhaps only the OP knows. As a non-LaTeX user, I think the LaTeX assumption, aside from being non-obvious, is frustrating even when you're aware of it, since it takes extra time to distinguish answers that don't apply outside of LaTeX to those that do. The assumption would be more understandable if this site were labeled latex.stackexchange.com. Sep 5, 2013 at 14:25

Almost all calculation systems work with real numbers, not lengths, and certainly don't allow arbitrary dimensions in calculations. (Try working out say an area in Excel: you'll need to convert your lengths to real numbers, then work out your area as a real number where the units are separate.)

TeX provides a 'native' way to store dimensions as they are needed for typesetting. Calculation-wise, these are limited as Knuth expected them to be used broadly for 'known quantities'. As pointed out in a comment, there are ways to build calculation engines on top of TeX: probably the most suitable given the description of the problem is the one built in to pgf: pgfmath. This allows a range of calculations to take a mixture of real values and lengths, and includes code to work out for example square roots. Areas and other 'higher-order' stuff will still need to be manually converted first.

A length can be converted to a number by prefixing it with \number. This gives its value in terms of the sp unit which is 1/65536 of a pt. However multiplying out two such things could easily exceed the TeX bound on integers which is 2^31. There is no concept of area in TeX and no \areaexpr provided by e-TeX either.

Note also, that although you may input lengths to TeX in various units pt, cm, in, etc..., there is no conversion back, and \the\<dimen> prints a value in pt unit (I just realized that LaTeX seemingly has NO command for the user to display the value of a length register defined by \newlength and set by \setlength; one only has at one's disposal the primitives \the and \number from TeX).

As xintexpr does exact algebraic computations with arbitrarily big numbers, and also knows to extract square roots with (by default) 16 digits of precision, you can use it (in combination with \dimexpr) for your problems.

\documentclass{article}
\usepackage{xintexpr}

\newlength{\lenA}
\newlength{\lenB}
\newlength{\lenC}
\newlength{\lenD}

\xintNewExpr{\Harmonic}[2]{round(2/(1/#1+1/#2))} % I added a 2 here
\newcommand{\HarmonicLen}[2]{\dimexpr\Harmonic {\number#1}{\number#2}sp\relax}

\xintNewExpr{\Pythagore}[2]{round(sqrt(#1^2+#2^2))}
\newcommand{\PythagoreLen}[2]{\dimexpr\Pythagore {\number#1}{\number#2}sp\relax}

% 1sp = 1/65536 pt.
% 1pt = 1/72.27 in.
% 1in = 2.54cm
% 1 sp^2 = 1/65536*1/65536 * 1/72.27 * 1/72.27 * 2.54 * 2.54 cm^2
%
\edef\ConvFactor {\xinttheexpr 1/65536*1/65536 * 1/72.27 * 1/72.27 * 2.54 *
2.54\relax }

\newcommand{\RectArea}[2]{%
\xintRound{4}{\xintPrd{{\number#1}{\number#2}{\ConvFactor}}}}

\begin{document}

\setlength{\lenA}{10pt}
\setlength{\lenB}{10pt}

\setlength{\lenC}{\HarmonicLen{\lenA}{\lenB}}
\setlength{\lenD}{\PythagoreLen{\lenA}{\lenB}}

\the\lenA,\the\lenB$\to$\the\lenC,\the\lenD    (or directly: \the\HarmonicLen{\lenA}{\lenB},
\the\PythagoreLen{\lenA}{\lenB})

\setlength{\lenA}{1cm}
\setlength{\lenB}{1cm}

\setlength{\lenC}{\HarmonicLen{\lenA}{\lenB}}
\setlength{\lenD}{\PythagoreLen{\lenA}{\lenB}}

\the\lenA,\the\lenB$\to$\the\lenC,\the\lenD

% (or directly: \the\HarmonicLen{\lenA}{\lenB},
% \the\PythagoreLen{\lenA}{\lenB})

\setlength{\lenA}{1cm}
\setlength{\lenB}{2cm}

\setlength{\lenC}{\HarmonicLen{\lenA}{\lenB}}
\setlength{\lenD}{\PythagoreLen{\lenA}{\lenB}}

\the\lenA,\the\lenB$\to$\the\lenC,\the\lenD

% (or directly:
% \the\HarmonicLen{\lenA}{\lenB},
% \the\PythagoreLen{\lenA}{\lenB})

\setlength{\lenA}{1in}
\setlength{\lenB}{2in}

\setlength{\lenC}{\HarmonicLen{\lenA}{\lenB}}
\setlength{\lenD}{\PythagoreLen{\lenA}{\lenB}}

\the\lenA,\the\lenB$\to$\the\lenC,\the\lenD

% (or directly: \the\HarmonicLen{\lenA}{\lenB},
% \the\PythagoreLen{\lenA}{\lenB})

\setlength{\lenA}{5cm}
\setlength{\lenB}{7cm}

The rectangle with sides of lengths 5cm (\the\lenA) and 7cm (\the\lenB) has an
area equal to \RectArea{\lenA}{\lenB} cm${}^2$.

\setlength{\lenC}{5in}
\setlength{\lenD}{7in}

The rectangle with sides of lengths 5in (\the\lenC) and 7in (\the\lenD) has an
area equal to \RectArea{\lenC}{\lenD} cm${}^2$.

The ratio of these two areas is \xinttheexpr
round(\RectArea{\lenC}{\lenD}/\RectArea{\lenA}{\lenB},4)\relax{}
and the square or
2.54 is \xinttheexpr round(sqr(2.54),4)\relax.

\end{document}


xfp provides a generalised way of performing algorithmic calculation on dimensionless quantities and lengths. "Dimensions [are] automatically expressed in points, e.g., pc is 12" (from the xfp documentation).

\documentclass{article}

\usepackage{xfp}

\begin{document}

\newlength{\lengthA}
\setlength{\lengthA}{2em}% 20.00003pt
\newlength{\lengthB}
\setlength{\lengthB}{8bp}% 8.03pt

Using \TeX: \the\dimexpr\lengthA + \lengthB + 12pt\relax % 40.03003pt

Using \verb|xfp|: \fpeval{round(\lengthA + \lengthB + 12pt, 5)}pt % 40.03003pt

Hypotenuse: \fpeval{sqrt(\lengthA^2 + \lengthB^2)}pt

Other length calculation: \fpeval{1 / ((1 / \lengthA) + (1 / \lengthB))}pt

\end{document}


Since \fpeval (and \inteval) is expandable, you can use this in length assignments as well:

\newlength{\hypotenuse}
\setlength{\hypotenuse}{\fpeval{sqrt(\lengthA^2 + \lengthB^2)}pt} % 21.55185pt


In ConTeXt (at least mkii), as in eTeX, you can use the commands \numexpr, \dimexpr, \glueexpr, and \muexpr. E.g.

\ifdim\dimexpr (2pt-5pt)*\numexpr 3-3*13/5\relax + 34pt/2<\wd20


Whether this helps you with your specific use case, I'm not sure. It does let you combine types within an expression, but I'm not sure you can avoid the conversion you're trying to avoid.

Nevertheless I wanted to put a reference to these commands on this page, since I was looking for them, and this question was the closest thing I could find to what I needed.