47

In the following minimal example, I have two equations inside an itemize environment, with an item per equations. Each equation is defined in its own equation environment.

\documentclass{article}
\usepackage{amstext}

\begin{document}

\begin{itemize}
 \item Lorem ipsum dolor sit amet, consectetur adipiscing elit:

 \begin{equation}
    f(x) = \left\{
    \begin{array}{l l}
      1 & \text{ nisl justo, hendrerit} \\
      0 & \text{ sagittis condimentum}\\
    \end{array} \right.
 \end{equation}

 \item Duis magna nunc, ultrices at fringilla non, feugiat sed massa:

 \begin{equation}
    g(x) = \left\{
    \begin{array}{l l}
      -1 & \text{ fermentum fringilla mauris eget} \\
      0 & \text{ gravida ipsum vitae}\\
    \end{array} \right.
 \end{equation}
\end{itemize}

\end{document}

However, each equation has its own alignment, giving the following result:

Result of minimal example

It would be nice (I think) if both equations could be aligned in the same way, something like this:

Equations aligned

Is this possible?

Note: it would be nice if the solution could be also applied to equations in different paragraphs.


UPDATE:

Ryan presented a very nice solution, which is currently the most upvoted, but it does not work quite well:

\documentclass{article}
\usepackage{amsmath}
\begin{document}
 This is a list.
 \begin{itemize}
   \item First item.
  \begin{align*}
  f(x) &= \begin{cases} 0 & \text{now} \\ 1 & \text{then} \end{cases}
  \intertext{\item Second item.}
  g(x) &= \begin{cases} 0 & \text{here and there}  \\ -1 & \text{to and fro} \end{cases}
  \end{align*}
 \end{itemize}
 After the list.
\end{document}

Ryan's result

Can you see? "now" and "then" are not aligned to "here and there" and "to and fro". Can we solve this? :)

5
  • Perhaps it's possible, but not desirable. I'm also open to hear your opinions :) Sep 21, 2011 at 17:02
  • 4
    To solve your "now-then", "to-fro" problem, you can use a \phantom in the first cases environment: \begin{cases} 0 & \text{now} \\ 1\phantom{-} & \text{then} \end{cases}. Sep 22, 2011 at 17:15
  • I second @Gonzalo's suggestion. No form of \intertexting can help you here, since you cross several environment boundaries. The only solution is a manual one: you have to adjust the widths yourself. A more extreme solution can possibly be obtained using the {alignat} environment combined with \intertext, but you would basically be reimplementing a lot of other things.
    – Ryan Reich
    Sep 22, 2011 at 19:42
  • I think the solution I provided already does this. Sep 23, 2011 at 2:05
  • Thank you very much for your answers. As soon as I have time, I'll try to evaluate Peter's and Ryan's solutions, to choose a recommend answer. Oct 18, 2011 at 17:23

4 Answers 4

16

I have encountered this situation a lot and the following method can be adapted to almost all cases. Similar to Barbara's solution, this involves deciding what is the largest text and using \makebox to set the type into a box equal to the width of the largest string.

If also inserted a few \phantoms to get exact alignment of the cases.

\documentclass{article}
\usepackage{amstext}

\newcommand*{\LongestText}{fermentum fringilla mauris }%
\newlength{\LargestSize}%
\settowidth{\LargestSize}{\LongestText}%
\newcommand*{\MakeBox}[1]{\makebox[\LargestSize][l]{#1}}%
\newcommand*{\MakeBoxText}[1]{\text{\MakeBox{#1}}}%

\begin{document}
\begin{itemize}
 \item Lorem ipsum dolor sit amet, consectetur adipiscing elit:

 \begin{equation}
    f(x) = \left\{
    \begin{array}{l l}
      1\phantom{-} & \MakeBoxText{ nisl justo, hendrerit} \\
      0\phantom{-} & \MakeBoxText{ sagittis condimentum}
    \end{array} \right.
 \end{equation}

 \item Duis magna nunc, ultrices at fringilla non, feugiat sed massa:

 \begin{equation}
    g(x) = \left\{
    \begin{array}{l l}
      -1 & \MakeBoxText{ fermentum fringilla mauris eget} \\
      \phantom{-}0 & \MakeBoxText{ gravida ipsum vitae}
    \end{array} \right.
 \end{equation}
\end{itemize}
\end{document}

Update: 2011-09-23: In order to be able to handle a general case you can use the technique shown above to each element of the function separately:

  1. the function name
  2. the case values
  3. the case text

Then each portion gets places in a fixed width box and everything lines up exactly even with more complicated expressions:

enter image description here

Below, I have three macros which are to be used for each of the portions. I have chosen a [r] alignment for the function name, and a [l] alignment for the case values and case text.

\documentclass{article}
\usepackage{amsmath}

\newcommand*{\LongestName}{\ensuremath{h(x)+g(x)}}% function name
\newcommand*{\LongestValue}{\ensuremath{-1}}% function value
\newcommand*{\LongestText}{fermentum fringilla mauris }%

\newlength{\LargestNameSize}%
\newlength{\LargestValueSize}%
\newlength{\LargestTextSize}%

\settowidth{\LargestNameSize}{\LongestName}%
\settowidth{\LargestValueSize}{\LongestValue}%
\settowidth{\LargestTextSize}{\LongestText}%

% Choose alignment of the various elements here: [r], [l] or [c]
\newcommand*{\MakeBoxName}[1]{{\makebox[\LargestNameSize][r]{\ensuremath{#1}}}}%
\newcommand*{\MakeBoxValue}[1]{\ensuremath{\makebox[\LargestValueSize][l]{\ensuremath{#1}}}}%
\newcommand*{\MakeBoxText}[1]{\makebox[\LargestTextSize][l]{#1}}%

\begin{document}
\begin{itemize}
 \item Lorem ipsum dolor sit amet, consectetur adipiscing elit:

 \begin{equation}
    \MakeBoxName{f(x)} = \left\{
    \begin{array}{l l}
      \MakeBoxValue{1} & \MakeBoxText{ nisl justo, hendrerit} \\
      \MakeBoxValue{0} & \MakeBoxText{ sagittis condimentum}
    \end{array} \right.
 \end{equation}

 \item Duis magna nunc, ultrices at fringilla non, feugiat sed massa:

 \begin{equation}
    \MakeBoxName{g(x)} = \left\{
    \begin{array}{l l}
      \MakeBoxValue{-1} & \MakeBoxText{ fermentum fringilla mauris eget}\\
      \MakeBoxValue{\phantom{-}0} & \MakeBoxText{ gravida ipsum vitae}
    \end{array} \right.
 \end{equation}

 \item Duis magna nunc, ultrices at fringilla non, feugiat sed massa:

 \begin{equation}
    \MakeBoxName{h(x)+g(x)} = \left\{
    \begin{array}{l l}
      \MakeBoxValue{\sin x} & \MakeBoxText{ fermentum fringilla mauris eget} \\
      \MakeBoxValue{0} & \MakeBoxText{ gravida ipsum vitae}
    \end{array} \right.
 \end{equation}
\end{itemize}
\end{document}

Not sure how you prefer to have the function values aligned, but this is how I have been aligning them. You can remove the \phantom{-} and and adjust the alignments as desired.

42

This is absolutely insane, but it works:

\documentclass{article}
\usepackage{amsmath}
\begin{document}
 This is a list.
 \begin{itemize}
   \item First item.
  \begin{align*}
  f(x) &= \begin{cases} 0 & \text{now} \\ 1 & \text{then} \end{cases}
  \intertext{\item Second item.}
  g(x) &= \begin{cases} 0 & \text{here and there}  \\ 1 & \text{to and fro} \end{cases}
  \end{align*}
 \end{itemize}
 After the list.
\end{document}

The amsmath alignment environments allow \intertext to insert non-alignment non-math text inside without exiting. The alignment is preserved across the insertion, which is what you want.

Caveat: the first \item must not be an \intertext, or else \itemize complains. The others, as you see, can be.

Example output:

aligning across itemize

8
  • 1
    This is great! I had no idea that \intertext is so flexible!
    – Mico
    Sep 21, 2011 at 18:54
  • 4
    @Mico: Honestly, neither did I. I just tried what a literal reading of its function would suggest is the right way; actually, given the Caveat, it seems to me that it is somewhat accidental that this works. I also tried putting the entire \itemize in \intertexts inside the {align}, but it choked.
    – Ryan Reich
    Sep 21, 2011 at 19:03
  • 1
    @Mico: It also doesn't work for equations aligned across paragraphs; {align} doesn't like paragraph breaks even inside \intertext.
    – Ryan Reich
    Sep 21, 2011 at 19:08
  • I think many of the commands and environments of the amsmath package don't like -- actually, they disallow -- blank lines and other forms of paragraph breaks. It would stand to reason that \intertext shares that feature.
    – Mico
    Sep 21, 2011 at 21:07
  • 3
    \intertext is basically just a fancy \noalign with contents inside a \vbox, so you can use \endgraf instead of `\\` or a blank line if you want another paragraph there.
    – morbusg
    Sep 22, 2011 at 18:43
7

Let me submit a second answer that also addresses the issue of aligning across paragraphs. It is equally insane...

\documentclass{article}
% \usepackage{showframe}
\usepackage{amsmath}

% It's like {align}, but simple!
\newenvironment{SimpleAlign}
{%
 \let\\=\cr
 \tabskip 0pt plus 1fil\relax
 \halign\bgroup
  &\hfil$\displaystyle ##$\tabskip 0pt\relax
  &$\displaystyle {}##$\hfil\tabskip 0pt plus 1fil\relax\cr
}
{%
 \crcr\egroup
}

% Saves its contents typeset like SimpleAlign.  You can give it a name.
\newenvironment{AlignAgain}[1][AlignBox]
{%
 \expandafter\let\expandafter\AlignAgainBox\csname #1\endcsname
 \setbox\AlignAgainBox=\vbox\bgroup\SimpleAlign
}
{%
 \endSimpleAlign\egroup
 \ReBox\AlignAgainBox
}
\newbox\AlignBox

% Prints the lines from {AlignAgain} one-by-one, with or without equation numbers as starred.  If you named the {AlignAgain}, use it here.
\makeatletter
\newcommand\ALineAgain{%
 \@ifstar
  {\AlignAgainStartrue\@ALineAgain}
  {\AlignAgainStarfalse\@ALineAgain}%
}
\newcommand\@ALineAgain[1][AlignBox]{%
 \expandafter\let\expandafter\AlignAgainBox\csname #1\endcsname
 \begin{equation*}
  \PutFirstBox\ifAlignAgainStar\AlignAgainBox
 \end{equation*}
}
\makeatother
\newif\ifAlignAgainStar

% Reboxes a box in the format: {[1][2]...[n]} -> {[1]{[2]{...}[n]}}
% {...} = \hbox
\newcommand{\ReBox}[1]
{%
 % To enter internal vertical mode, where \lastbox is valid
 \setbox0=\vbox{%
  \unvbox#1\relax
  \global\setbox#1=\hbox{\hbox{}}
  \loop
   \unskip
   %\box0 is the box currently at the end of #1
   \setbox0=\lastbox
  \ifvoid0\relax
  \else
   \global\setbox#1=\hbox{\box0\box#1}%
  \repeat
 }%
}

% Puts the first box in a nested-box list into the display, saving the rest back in #1
% Optionally places an equation number
\newcommand{\PutFirstBox}[2]{%
 \hbox to \displaywidth{%
  \unhbox#2\relax
  \global\setbox#2=\lastbox
  \setbox0=\lastbox
  \unhbox0%
  #1\else\refstepcounter{equation}\llap{(\theequation)}\fi
 }%
}

\begin{document}
\begin{AlignAgain}
 a &= b & c &= d \\
 f(x) &= g(x) & h(x) &= e^{-1/x^2}
\end{AlignAgain}

This is a paragraph with a lot of redundant words whose only purpose is to extend it onto a new line or two so it's dramatic when I display this equation:
\ALineAgain*
and then follow it with a bunch more text.

And also a new paragraph, just for good measure.  I wonder if the two equations will line up?  I sure hope so!
\ALineAgain
This is sort of fun.
\end{document}

My first thought was to hack apart the result of an {align} and dole out the lines one-by-one wherever you want them. Alas, {align} produces a list of considerable complexity and it is not worth the effort to unravel it (if that's even possible).

So I made my own alignment environment that, as far as I can tell, does what you'd want {align*} to do but produces a very simple list. My macro \ALineAgain then picks that list apart and drops the lines one at a time wherever you ask.

Because the lines are not printed where the alignment is actually given, it makes no sense to have an {AlignAgain*}; it never prints equation numbers. Instead, the \ALineAgain macro takes a star that suppresses the addition of an equation number.

6

this is definitely a kludge, and it requires knowing what bit is the longest, but it should do the job. for the first bit of text in the shortest case, instead of just entering the text to be printed, use a phantom to force the width, and \rlap to position the printing text:

1 & \text{\rlap{ nisl justo, hendrerit}\phantom{ fermentum fringilla mauris eget}} \\

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .