如何避免显示方程式后的孤线

如何避免显示方程式后的孤线

如果显示的方程式接近页面底部,TeX 会插入分页符,即使当前段落在方程式后只包含一行,例如

... it follows that
\[
  a_n = ...
\]
for all $n\in\N$.

(尽管当前页面有足够的空间,但这种情况仍然会发生。)问题似乎是 TeX 不把显示方程式后面的孤行视为孤行。

因为我不喜欢这种行为,所以我想出了以下解决方法:我\avoidbreak在结束之前写入\],其中\avoidbreak定义为

\newcommand{\avoidbreak}{\postdisplaypenalty=100}

当然,现在我必须在每次出现可能“不好”的分页符时都进行书写,这很麻烦\avoidbreak。我不想全局定义\postdisplaypenalty=100因为这会阻止在显示方程式后分页,即使在段落末尾也是如此:对于新段落显示之后立即从下一页开始也是完全没问题的(即使它只包含一行,另请参阅下面的 MWE)。

现在我的问题是:是否有一个干净的解决方案,无需手动添加类似的东西\avoidbreak?我很感激一些可以添加到我的序言中的代码。

\documentclass{article}
%Remove the following % to get "one line of text" onto the first page:
%\postdisplaypenalty=100
\setlength\textheight{3.65cm}
\setlength\textwidth{4cm}
\begin{document}
Two lines of text followed by a formula
\[a=b\]
Two lines of text followed by a formula
\[a=b\]
%With my code, there will be no change if you put an empty line at this place!
%If "one line of text" below starts a new paragraph, then
%that paragraph should be allowed (even encouraged) to start on a new page.
%I only want to try and avoid the page break if no new paragraph is started here.
one line of text

New paragraph
\end{document}

(让我提一下,TeX 有一个\displaywidowpenalty参数,但这个参数是关于寡妇的显示的方程式。

答案1

我看不出设置有什么问题\postdisplaypenalty全局设置有什么问题——如果你遇到任何问题,它们可能是软件包错误的迹象。默认值可能对 Knuth 来说没问题;但这些设置是作为参数实现的,因为你应该定制它们。

答案2

好的,我不知道这是一个多么糟糕的黑客行为,但这是一个尝试\par在末尾重新定义的尝试\],以便它可以检测它是否直接出现在显示的数学之后。

\documentclass{article}
\usepackage{etoolbox}
%Remove the following % to get "one line of text" onto the first page:
\postdisplaypenalty=100
\setlength\textheight{3.65cm}
\setlength\textwidth{4cm}

\makeatletter
\patchcmd\]{\ignorespaces}
{%
   % We are in horizontal mode here again!
   % Insert a penalty so we can recognize whether \par comes directly
   % after. 
   \penalty6666
   % This might conflict with \par redefinitions in lists, so only
   % proof of concept!
   \def\par
   {%
     % check whether we are directly behind formula
     \@tempcnta=\lastpenalty\unpenalty
     \@par
     % in that case - insert negative penalty!
     \ifnum6666=\@tempcnta\addpenalty\m@ne\fi
   }%
   \ignorespaces
}{}{}
\makeatother

\begin{document}
\tracingoutput1
\showboxdepth1000
\showboxbreadth1000
Two lines of text followed by a formula
\[a=b\]
Two lines of text followed by a formula
\[a=b\]
%With my code, there will be no change if you put an empty line at this place!
%If "one line of text" below starts a new paragraph, then
%that paragraph should be allowed (even encouraged) to start on a new page.
%I only want to try and avoid the page break if no new paragraph is
%started here.

one line of text

New paragraph
\end{document}

这可能充其量只是概念的初步证明,但至少你可以基于此开始进行真正的测试。

答案3

如果您确实不想postdisplaypenalty全局设置该值,您可以创建一个新环境,修改环境内的显示惩罚,并在离开之前重置它。

\makeatletter
\newenvironment{tighten}{
    \let\pen@old\postdisplaypenalty
    \postdisplaypenalty=100
}{
    \let\postdisplaypenalty=\pen@old
}
\makeatother

输出

修改后的MWE代码:

\documentclass{article}

\makeatletter
\newenvironment{tighten}{
    \let\pen@old\postdisplaypenalty
    \postdisplaypenalty=100
}{
    \let\postdisplaypenalty=\pen@old
}
\makeatother

%Remove the following % to get "one line of text" onto the first page:
%\postdisplaypenalty=100
\setlength\textheight{3.65cm}
\setlength\textwidth{4cm}
\begin{document}
\begin{tighten}
    Two lines of text followed by a formula
    \[a=b\]
    Two lines of text followed by a formula
    \[a=b\]
\end{tighten}
%It doesn't matter if you have a new line at this place or not!
%I only want to avoid the page break if no new paragraph is started here.
one line of text

New paragraph
\end{document}

相关内容