Using operator spacing to indicate precedence

I regularly have to typeset equations that are, because of their inherent complexity, difficult to read. To address this I have gotten into the habit of emphasizing operator precedence by horizontal spacing.

To give a simple example, because in mathematics \times binds stronger than +, and + binds stronger than =, I would do things like this:

$a \times b \; + \; c \times d \;\; = \;\; (e + f) \times g$


I've found that this immediately makes it easier to understand an equation at a glance.

Well, since then I have devised a way that is a little nicer than that, defining a family of custom 'math ligatures' using the semantic package:

$a * b + c * d = (e + f) * g$


Increasing the number of backticks exponentially increases the extra space, and I've experimentally come up with lengths that appear most pleasing to the eye. The implementation comes down to the following (though I have left out a number of corner cases and features, such as encoding \times as *):

\RequirePackage [ligature] {semantic}

\mathlig{}{\mspace{38mu}}
\mathlig{}{\mspace{23mu}}
\mathlig{}{\mspace{12mu}}
\mathlig{}{\mspace{5mu}}


Have other people already attempted something similar? Is there a way to do this better / easier / automatically?

On a more philosophical note (and I hope this doesn't violate the spirit of stackexchange; mods, please let me know if I should remove this), I somehow expect this to be a controversial approach. After all, many die-hard TeX users go through great lengths to preserve the beautiful spacing that TeX generates. I would actually like to hear from you. How do you solve the problem of formula readability?

• The "philosophical" questions seems off-topic. For the technical one, seeing how you did the trick may help in finding a handier syntax. – egreg Jun 30 '13 at 15:19
• I put the "philosophical" part more in the background for now, and given working code from the 'backtick' implementation. – mhelvens Jun 30 '13 at 15:34
• On the philosophical question: I think that using whitespace for semantics is (in general) not a good idea. tabs instead of spaces in a makefile have always bothered me. How about extra pairs of parentheses when they're helpful? – Ethan Bolker Jun 30 '13 at 17:09
• Firstly, I don't have a clue what tabs vs. spaces has to do with this. :-) --- Secondly, I wouldn't be using whitespace for semantics at all. I'd still use parentheses where necessary (as in my example above). The whitespace is just for extra clarity. --- Thirdly, I've found that using even more parentheses will actually make a formula less clear. It just adds to the number of symbols that have to be 'parsed' by the reader. – mhelvens Jun 30 '13 at 17:32
• You can't use different values of \medmuskip or similar parameters in the same formula: TeX uses the value that's current at the end of the formula. If your scope is limited to the four symbols \times, +, - and = one can probably do it without resorting to such markup. – egreg Jun 30 '13 at 20:03

If your scope is limited to the main arithmetical ones, that is, plus, minus, times and equals, you can do the same without any markup.

Just define the characters +, -, * and = to be math active.

Here's a Plain TeX document, the same will do with LaTeX (if you load amsmath the declarations \mathcode+="8000 and similar ones should be inside the argument to \AtBeginDocument).

\mathchardef\plus=\mathcode+
\mathchardef\minus=\mathcode-
\mathchardef\equals=\mathcode=

\begingroup\lccode~=+
\lowercase{\endgroup\def~}{\mkern12mu\plus\mkern12mu}
\begingroup\lccode~=-
\lowercase{\endgroup\def~}{\mkern12mu\minus\mkern12mu}
\begingroup\lccode~=*
\lowercase{\endgroup\def~}{\mkern5mu\times\mkern5mu}
\begingroup\lccode~==
\lowercase{\endgroup\def~}{\mkern23mu\equals\mkern23mu}

\mathcode+="8000
\mathcode-="8000
\mathcode*="8000
\mathcode=="8000

$$a * b + c * d = (e * f) - g$$
\bye


Of course in LaTeX one should use $...$ instead of $$...$$. You can also activate this "on demand":

\mathchardef\plus=\mathcode+
\mathchardef\minus=\mathcode-
\mathchardef\equals=\mathcode=

\def\spacedmath{%
\begingroup\lccode~=+
\lowercase{\endgroup\def~}{\mkern12mu\plus\mkern12mu}
\begingroup\lccode~=-
\lowercase{\endgroup\def~}{\mkern12mu\minus\mkern12mu}
\begingroup\lccode~=*
\lowercase{\endgroup\def~}{\mkern5mu\times\mkern5mu}
\begingroup\lccode~==
\lowercase{\endgroup\def~}{\mkern23mu\equals\mkern23mu}
\mathcode+="8000
\mathcode-="8000
\mathcode*="8000
\mathcode=="8000
}

$$\spacedmath a * b + c * d = (e * f) - g$$
$$a * b + c * d = (e * f) - g$$
\bye The usefulness of this from a pedagogical point of view is dubious.

• An instructive answer! No, my real-life examples are not limited to these simple operators, but that's not really an issue. All the operators I use can be made similarly active (or are already macros). --- But this solution is lacking in one important respect: all operators have a fixed spacing. The spacing should ideally depend on the other operators surrounding it. If I don't use * then + doesn't need extra spacing. Moreover, a + within parenthesis should get less spacing than a * on the outside. --- I suppose I need a full-fledged parser. :-) – mhelvens Jun 30 '13 at 21:21
• @mhelvens I recently found this question of yours, and have reached the same conclusion as you after attempting to explore solutions to the same problem. I think it seems that writing a parser is the best approach in order to automate things. Besides that though, I really like your approach using  with the semantics package. – user89 Sep 23 '17 at 19:18