Как сделать так, чтобы разделители \left, \right автоматически (!) имели одинаковый размер, несмотря на переносы строк?

Как сделать так, чтобы разделители \left, \right автоматически (!) имели одинаковый размер, несмотря на переносы строк?

Этот код

\documentclass{article}

\usepackage{amsmath}

\begin{document}
\begin{align*}
\begin{split}
    z = \left( a + b + c \right. \\ 
        \left. + \frac{d}{e} \right)
\end{split} 
\end{align*}
\end{document}

выдает следующий результат:

введите описание изображения здесь

Два разделителя имеют разные размеры. Обычный трюк для получения соответствующих размеров — использовать \vphantomвот так:

\documentclass{article}

\usepackage{amsmath}

\begin{document}
\begin{align*}
\begin{split}
    z = \left( a + b + c +\vphantom{\frac{d}{e}}\right. \\  
        \left. + \frac{d}{e} \right)
\end{split} 
\end{align*}
\end{document}

что дает следующий результат:

введите описание изображения здесь

Однако такой подход

  • становится быстросложныйпо мере увеличения количества переносов строк;
  • являетсяне подлежит обслуживанию(поскольку, если содержимое строки изменится, аргумент \vphantomможет также потребоваться изменить, чтобы получить желаемый результат).

Альтернативный подход 1: вручную задать размер разделителей (используя \bigи т.п.). К сожалению, это тоже не очень удобно для поддержки.

Альтернативный подход 2: использование некоторой математической среды, предоставляемой пакетом breqn, которая позволяет переносить строки между двумя разделителями \left/ \rightи заботится о размере разделителя. Однако я бы хотел держаться подальше от breqn, если это возможно.


Можете ли вы придумать способ сделать так, чтобы связанные разделители \left/ right\автоматически имели одинаковый размер, несмотря на переносы строк, без (явного) использования трюка \vphantom? В идеале решение должно работать для нескольких вложенных пар разделителей. Например, в следующем примере внутренние разделители должны иметь одинаковый размер, а внешние разделители должны иметь одинаковый размер:

\left( \left( ... \right. \right. \\
\left. \left. ... \right) \right)

решение1

В следующем примере package используется zrefдля запоминания размера математической формулы в метках. Package mleftrightиспользуется для уменьшения дополнительного горизонтального интервала на \leftи \right.

Внутри сложного математического блока можно использовать следующие макросы:

\mzleft{<label>}{<left delimiter>}{<math formula>}
\mzright{<label>}{<math formula>}{<right delimiter>}

Макросы могут быть вложенными, необходимо <label>для идентификации пар разделителей. Внутри математического блока (математическая среда, ...) имена <label>пар должны быть уникальными. После этого \mzresetможно вызвать математический блок. Он освобождает <label>имена, и их можно использовать повторно.

Пример файла:

\documentclass{article}

\usepackage{amsmath}
\usepackage{mleftright}
\usepackage{zref-base}

\makeatletter
\zref@newprop{mzheight}[0pt]{\the\ht\z@}
\zref@newprop{mzdepth}[0pt]{\the\dp\z@}
\newcount\c@@mz
\newcommand*{\the@mz}{mz\the\c@@mz}
\newcommand*{\@mz@list}{}    
\let\@mz@do\relax
\newcommand*{\mzreset}{%
  \begingroup
    \def\@mz@do##1{%
      \global\expandafter\let\csname mz@##1\endcsname\relax
    }%
    \@mz@list
    \global\let\@mz@list\@empty
  \endgroup
}
\newcommand*{\mzleft}[3]{%
  \@ifundefined{mz@#1}{%
    \global\advance\c@@mz\@ne
    \expandafter\xdef\csname mz@#1\endcsname{\the@mz}%
    \xdef\@mz@list{\@mz@list\@mz@do{#1}}%
  }{}%
  \expandafter\let\expandafter\@mz\csname mz@#1\endcsname
  \mleft#2%
  \expandafter\mathpalette\expandafter{%
    \expandafter\@mzleft\expandafter{\@mz}%
  }{#3}%
  \mright.\kern-\nulldelimiterspace
}
\newcommand*{\mzright}[3]{%
  \kern-\nulldelimiterspace
  \@ifundefined{mz@#1}{%   
    \@latex@warning{Missing \string\mzleft{#1}}%
    \mleft.#2\mright#3%
  }{%
    \expandafter\let\expandafter\@mz\csname mz@#1\endcsname
    \mleft.%
    \expandafter\mathpalette\expandafter{%
      \expandafter\@mzright\expandafter{\@mz}%
    }{#2}%
    \mright#3%
  }%
}   
\newcommand*{\@mzleft}{%
  \@mzleftright lr%
}
\newcommand*{\@mzright}{%
  \@mzleftright rl%
}
\newcommand*{\@mzleftright}[5]{%
  \sbox0{$\m@th#4{}#5{}$}%
  \ifmeasuring@
  \else
    \begingroup
      \let\@auxout\@mainaux
      \zref@labelbyprops{#3#1}{mzheight,mzdepth}%
    \endgroup
  \fi
  \zifrefundefined{\@mz #2}{%
  }{%
    \dimen@=\zref@extract{#3#2}{mzheight}\relax
    \ifdim\dimen@>\ht0 %
      \ht0=\dimen@
    \fi
    \dimen@=\zref@extract{#3#2}{mzdepth}\relax
    \ifdim\dimen@>\dp0 %
      \dp0=\dimen@
    \fi
  }%   
  \copy0\relax
}
\makeatother

\begin{document}
\begin{align*}
\begin{split}
    z = \mzleft{a}({ a + b + c +} \\
        \mzright{a}{{}+ \frac{d}{e}})
\end{split} 
\end{align*}   

\mzreset

\begin{align*}
\begin{split}
    z = \mzleft{a}{[}{%
          a + b + \frac{c}{d} +
          \mzleft{b}{(}{
            \int_0^\infty \mathrm{d}x
          }   
        } \\  
        \mzright{b}{
          + y}{)
        }
        \mzright{a}{
          + \frac{\displaystyle\sum_{i=0}^{100}i}{e}
        }{]}
\end{split}   
\end{align*}  
\end{document}

Результат

решение2

Хотя я считаю, что а) \bigls предпочтительнее, а б) увеличение разделителей стоит на одном уровне с ручной расстановкой переносов и случайными \enlargethispages в самом конце вычитки, вы можете обнаружить, что что-то вроде этого делает их немного более удобными в поддержке:

\newcommand\SPLIT[2]{%
  \left( #1\vphantom{#2}\right. \\
  \left. \vphantom{#1}#2\right) \\
}

\begin{align*}
  \begin{split}
    z= \SPLIT{a + b + c +}{d +\frac{d}{e}}
  \end{split}
\end{align*}

По крайней мере, это избавляет от ручного повторения аргумента о размере. Я уверен, что если бы кто-то был достаточно склонен, его можно было бы расширить для обработки переменного количества строк.

решение3

Стоит отметить: nathпакет поддерживает это, хотя, к сожалению, он несовместим со многими другими пакетами.

Взято прямо из документации, с некоторыми изменениями (*):

%! TEX program = lualatex
\documentclass{article}
\usepackage{nath}
\begin{document}
\[
\sin 2nx = 2n \cos x [\sin x \\
\qquad + \sum_{k = 1}^n (-4)^k
\frac{(n^2 - 1^2)(n^2 - 2^2) \dots (n^2 - k^2)}{(2k - 1)!}
\sin^{2k - 1} x]
\]
\end{document}

Выход:

выход

Смотрите также:

(*): С naththen $$и \[полностью эквивалентны. В противном случае, $$ ... $$это неподдерживаемый синтаксис LaTeX, см.Почему \[ ... \] предпочтительнее, чем $$ ... $$?.

решение4

Поскольку этот вопрос был поднят недавно и на него уже есть принятый ответ, я считаю, что будет уместно также добавить ответ, использующий ConTeXt, поскольку это может заинтересовать некоторых пользователей.

В ConTeXt формулы по умолчанию разбиваются по строкам, и в ограждениях могут быть разрывы. Ручные разрывы строк делаются с помощью \breakhere.

\starttext
\samplefile{tufte}

\startformula[align=slanted,margin=2em]
    \int_0^1 \frac{x^9}{(x^2+1)^{16}} \dd x 
    = \int_0^1 \left[
         \frac{x} {(x^2+1)^{12}}
        -\frac{4x}{(x^2+1)^{13}}
        +\frac{6x}{(x^2+1)^{14}}
        \breakhere
        -\frac{4x}{(x^2+1)^{15}}
        +\frac{x} {(x^2+1)^{16}}
        \right] \dd x
\stopformula

\samplefile{douglas}
\stoptext

формула, которая проходит по двум линиям, разделенным внутри забора

Связанный контент