linenomath 在 multline、align、flalign 环境的最后一行打印额外的数字

linenomath 在 multline、align、flalign 环境的最后一行打印额外的数字

我在用

\usepackage{lineno}

在我的文档上打印行号。我的文档有很多方程式。我使用

\usepackage{mathtools}

并经常使用诸如alignmultlineflalign等环境(我也使用它们带星号的*等效环境)。有一个名为mathlines

\usepackage[mathlines]{lineno}

据我所知,它仅打印环境数字equation

我已经读过,为了让行号适用于所有数学环境,你需要将每个环境包装在

\begin{linenomath*}
  \begin{align} % or equation,multline,flalign etc 
    .
    .
  \end{align} 
\end{linenomath*}

并删除该选项mathlines。请参阅这个答案为什么当段落后面跟着缩进的公式时,lineno 不会对段落进行编号?。这对我来说是可行的,但我有两个问题:

  1. 它给我一些等式的最后一行“额外”的数字;
  2. 我的文档中有数百个方程式。我不可能逐一浏览并添加begin{linenomath*}每个方程式。

这些问题有解决方案吗?这是我的输出。请注意成堆的数字 (4 , 5)、(7 , 8) 和 (11 , 12)。

enter image description here

代码

\documentclass[12pt,a4paper]{report}
\usepackage{mathtools}
\usepackage{lineno}
\linenumbers

\begin{document}

\begin{linenomath*}
\begin{equation}
    F=ma
\end{equation}
\end{linenomath*}

\begin{linenomath*}
\begin{multline}
p(x) = 3x^6 + 14x^5y + 590x^4y^2 + 19x^3y^3\\ 
- 12x^2y^4 - 12xy^5 + 2y^6 - a^3b^3
\end{multline}
\end{linenomath*}

\begin{linenomath*}
\begin{align} 
2x - 5y &=  8 \\ 
3x + 9y &=  -12
\end{align}
\end{linenomath*}

\begin{linenomath*}
\begin{flalign}
a &= b+c &\\
  &= 1+1 &\\
  &= 2  &
\end{flalign}
\end{linenomath*}

\end{document}

答案1

问题 1:

lineno包在每个显示方程的末尾打印一个行号,以及方程内任何两行之间的行号(在这两行中的第一行)。amsmath然而,对于环境,它还会在最后一行之后打印一个“显示间”行号,因此您应该隐藏“显示后”行号。

该包通过大量减少惩罚来强制(然后中止)分页。linenomath*环境调用\linenomathWithnumbers,其中包含行\advance\postdisplaypenalty\linenopenalty。从定义中删除此行将删除虚假的行号,但也会删除环境的唯一行号equation

您可以在 MWE 中添加\postdisplaypenalty=0(默认值)after\begin{linenomath*}和 before ,这将解决问题 1。\begin{<multline/align/flalign>}

问题2:

修补数学环境以包含的效果linenomath*并不太难。我已定义命令\linenomathpatch和,\linenomathpatchAMS它们在下面执行此操作。第一个命令用于基本数学环境(equationeqnarray),后者用于amsmath环境。这些环境的带星号和不带星号的版本都已修补。我使用\patchcmdetoolbox\linenopenalty包中删除不需要的更改\linenomath

代码:

以下代码完成了上面描述的两件事:

\documentclass[12pt,a4paper]{report}
\usepackage[mathlines]{lineno} %% <- mathlines turns on line numbering in equations
\usepackage{amsmath}           %% <- N.B., mathtools also loads this
\linenumbers

\usepackage{etoolbox} %% <- for \cspreto, \csappto, \patchcmd, \pretocmd, \apptocmd

%% Patch 'normal' math environments:
\newcommand*\linenomathpatch[1]{%
  \cspreto{#1}{\linenomath}%
  \cspreto{#1*}{\linenomath}%
  \csappto{end#1}{\endlinenomath}%
  \csappto{end#1*}{\endlinenomath}%
}
%% Patch AMS math environments:
\newcommand*\linenomathpatchAMS[1]{%
  \cspreto{#1}{\linenomathAMS}%
  \cspreto{#1*}{\linenomathAMS}%
  \csappto{end#1}{\endlinenomath}%
  \csappto{end#1*}{\endlinenomath}%
}

%% Definition of \linenomathAMS depends on whether the mathlines option is provided
\expandafter\ifx\linenomath\linenomathWithnumbers
  \let\linenomathAMS\linenomathWithnumbers
  %% The following line gets rid of an extra line numbers at the bottom:
  \patchcmd\linenomathAMS{\advance\postdisplaypenalty\linenopenalty}{}{}{}
\else
  \let\linenomathAMS\linenomathNonumbers
\fi

\linenomathpatch{equation}
\linenomathpatchAMS{gather}
\linenomathpatchAMS{multline}
\linenomathpatchAMS{align}
\linenomathpatchAMS{alignat}
\linenomathpatchAMS{flalign}

\begin{document}

\begin{equation}
    F = m a
\end{equation}

\begin{multline}
p(x) = 3x^6 + 14x^5y + 590x^4y^2 + 19x^3y^3\\
- 12x^2y^4 - 12xy^5 + 2y^6 - a^3b^3
\end{multline}

\begin{align}
2x - 5y &=  8 \\
3x + 9y &=  -12
\end{align}

\begin{flalign}
a &= b + c &\\
  &= 1 + 1 &\\
  &= 2  &
\end{flalign}

\end{document}

output

注意:我是amsmath在之后加载的lineno,但另一种顺序也可以。如果使用另一种顺序,equation\[最终将被修补两次(因为lineno也会修补它们),这不是很优雅,但完全无害。

附录:multline

正如你在上面的截图中看到的,multline这是唯一一个运行不正常的 ASM 环境,因为它在右侧有一个额外的行号多于方程。这个额外的数字是由额外的显示间惩罚(而不是预显示惩罚)引起的,它发生在“测量”阶段,当amsmath排版组成方程的单元格只是为了确定环境的每个列应该有多宽时。我真的不知道有什么不同/为什么multline不同。

可以通过修补amsmath内部命令来修复此问题\measure@,如下所示。以下内容需要添加到 之后的任意位置的前言中\usepackage{amsmath}

% Disable line numbering in measurement phase for multline
\makeatletter
\patchcmd{\mmeasure@}{\measuring@true}{
  \measuring@true
  \ifnum-\linenopenaltypar>\interdisplaylinepenalty
    \advance\interdisplaylinepenalty-\linenopenalty
  \fi
  }{}{}
\makeatother

我没有在上面的演示中包含这一点,因为我相信multline没有太多人使用它。


解释:lineno底层是如何工作的

这个lineno包相当复杂,我应该指出,我并不完全理解它的工作原理。以下是我认为可以理解的内容:

  1. \linenumbers将段落中两行之间的分页符惩罚值减少 100000。由于惩罚值通常介于 -10000 和 +10000 之间(少一个 0),这通常几乎可以保证强制在任意两行之间分页(任何低于 -10000 的值都会强制分页)。

  2. 该包还挂接到输出例程中。每当要发送页面时,它都会测试惩罚是否低于 -32000(通常不会发生这种情况)。如果是,它会打印一个数字,将惩罚增加 100000(取消之前的减少),并实质上告诉 TeX 重新考虑分页符。如果不低于 -32000,则页面将正常发送。

  3. linenomath*环境将方程式上方/下方分页符和方程式内行之间的惩罚减少了 100000。对于普通方程式,只有“显示后”和“显示前”惩罚是相关的,但“显示间”惩罚也会发生在环境中的任意两行之间amsmath(包括最后一行之后)。

这是由显示后惩罚引起的伪分页符,它会产生额外的不需要的数字,因此将该值设置回零(或从一开始就不改变它)可以解决您的问题。

相关内容