LaTeX 浮动不会增加垂直可拉伸性,也不会增加页面总高度 (t),但会降低目标高度 (h)。为什么?如何更改?

LaTeX 浮动不会增加垂直可拉伸性,也不会增加页面总高度 (t),但会降低目标高度 (h)。为什么?如何更改?

前言

这个问题是这个问题更准确地说,我能够追溯问题的根源,尤其是我能够生成三个 MWE 来说明问题。但是,我不确定是否最好完全重写原始问题(从而使问题下面的评论变得语无伦次)或提出一个新问题。我决定选择后者。您不需要阅读原始问题,这个问题是独立的。(抱歉,帖子很长,但问题很难解释。)

问题

我对梅花/寡妇非常挑剔。有趣的是,大多数梅花和寡妇主要出现在具有多个浮动的页面上。这很了不起,因为浮动及其可拉伸的上下垂直跳跃实际上应该为 LaTeX 提供额外的灵活性以避免梅花/寡妇。然而,我不得不了解到恰恰相反,即浮动使 TeX 分页算法更难找到好的分页符。我想知道

  1. 为什么要这样实施,以及
  2. 有解决办法吗?

第 1 届 MWE

请注意,此 MWE才不是使用浮动,但页面顶部有“静态”垂直框,它们占据的空间与第三个 MWE 中的最终浮动相同。我想强调的是,可拉伸跳过\floatsep\textfloatsep硬编码在与实际浮动相同的位置。此外,该行\clubpenalty=150不是必需的(因为 150 是默认值),但这样 MWE 更容易比较。

我建议使用普通乳胶(而不是 pdflatex)编译以下 MWE,以保持日志文件简洁。

\documentclass{article}

\clubpenalty=150
\flushbottom
\renewcommand\topfraction{.9}
\renewcommand\textfraction{.05}
\nofiles
\tracingpages=1

\begin{document}

\hrule
\vskip 75pt
\centerline{First float}
\vskip 100pt
\hrule
\vskip\floatsep
\hrule
\vskip 75pt
\centerline{Second float}
\vskip 100pt
\hrule
\vskip\textfloatsep

This paragraph is simply meant to be filler in order to illustrate the problem.
We deliberately did not use the more common ``Lore ipsum'' to not confuse \TeX\ hyphenation mechanism.
With this minimal working example (MWE) we want to pin down a problem, when \TeX/\LaTeXe\ calculates the badness of a page.
It seems that the additional vertical flexibility that is provided by floats are not considered.

The text height equals \the\textheight, the baseline skip equals \the\baselineskip, the separation between the last top float or the first bottom float and the text equals \the\textfloatsep, the separation between an in-text float and the surrounding text equals \the\intextsep, and the separation between consecutive floats equals \the\floatsep.

To this end, we need at least two paragraphs that both are at least four lines long.
Four lines are the minimum to split a paragraph across pages without creating a club or widow.
Unfortunately, we run out of ideas what we could write to fill the remaining lines.
Maybe a quote from literature is our rescue: ``Be or not to be, that is the question''.
Yes, this is enough.
\end{document}

结果是在页面末尾出现了一个令人不快的俱乐部(第 3 段的第 1 行)。

第一个 MWE 的插图

第二届

在此 MWE 中,俱乐部的处罚有所增加,但除此之外,它与第一个 MWE 相同。

\documentclass{article}

\clubpenalty=2000
\flushbottom
\renewcommand\topfraction{.9}
\renewcommand\textfraction{.05}
\nofiles
\tracingpages=1

\begin{document}

\hrule
\vskip 75pt
\centerline{First float}
\vskip 100pt
\hrule
\vskip\floatsep
\hrule
\vskip 75pt
\centerline{Second float}
\vskip 100pt
\hrule
\vskip\textfloatsep

This paragraph is simply meant to be filler in order to illustrate the problem.
We deliberately did not use the more common ``Lore ipsum'' to not confuse \TeX\ hyphenation mechanism.
With this minimal working example (MWE) we want to pin down a problem, when \TeX/\LaTeXe\ calculates the badness of a page.
It seems that the additional vertical flexibility that is provided by floats are not considered.

The text height equals \the\textheight, the baseline skip equals \the\baselineskip, the separation between the last top float or the first bottom float and the text equals \the\textfloatsep, the separation between an in-text float and the surrounding text equals \the\intextsep, and the separation between consecutive floats equals \the\floatsep.

To this end, we need at least two paragraphs that both are at least four lines long.
Four lines are the minimum to split a paragraph across pages without creating a club or widow.
Unfortunately, we run out of ideas what we could write to fill the remaining lines.
Maybe a quote from literature is our rescue: ``Be or not to be, that is the question''.
Yes, this is enough.
\end{document}

球杆消失了,额外的空白空间均匀分布在可伸缩跳跃上。

第二 MWE 插图

第三届世界妇女运动大会

这个 MWE 实际上使用了“正确”的浮点数。请注意,垂直跳跃\floatsep\textfloatsep 不是浮标本身的一部分,因为它们会掉落之间浮点数,是浮点数定义的一部分。我们强调\clubpenality保持高值。

\documentclass{article}

\clubpenalty=2000
\flushbottom
\renewcommand\topfraction{.9}
\renewcommand\textfraction{.05}
\nofiles
\tracingpages=1

\begin{document}

\begin{figure}[t]
\hrule
\vskip 75pt
\centerline{First float}
\vskip 100pt
\hrule
\end{figure}
\begin{figure}[t]
\hrule
\vskip 75pt
\centerline{Second float}
\vskip 100pt
\hrule
\end{figure}

This paragraph is simply meant to be filler in order to illustrate the problem.
We deliberately did not use the more common ``Lore ipsum'' to not confuse \TeX\ hyphenation mechanism.
With this minimal working example (MWE) we want to pin down a problem, when \TeX/\LaTeXe\ calculates the badness of a page.
It seems that the additional vertical flexibility that is provided by floats are not considered.

The text height equals \the\textheight, the baseline skip equals \the\baselineskip, the separation between the last top float or the first bottom float and the text equals \the\textfloatsep, the separation between an in-text float and the surrounding text equals \the\intextsep, and the separation between consecutive floats equals \the\floatsep.

To this end, we need at least two paragraphs that both are at least four lines long.
Four lines are the minimum to split a paragraph across pages without creating a club or widow.
Unfortunately, we run out of ideas what we could write to fill the remaining lines.
Maybe a quote from literature is our rescue: ``Be or not to be, that is the question''.
Yes, this is enough.
\end{document}

令人惊奇的是,该俱乐部又出现了。

第三届 MWE 插图

分页算法

要理解 TeX 如何决定分页符,以下术语很重要。

坏处: 糟糕之处b页面布局(或更准确地说,垂直框列表)的“粘连必须拉伸或收缩以形成所需大小的 [框] 的比率的立方乘以 100”。最初,此定义是针对水平框和段落行给出的(参见 TeXbook 第 14 章第 97 页),但“垂直不良度的计算规则与水平不良度相同”(TeXbook 第 15 章第 111 页)。

惩罚:惩罚是与断点关联的整数值。例如,如果在段落之间分页,则为零;\clubpenalty如果分页会导致出现分节符,则为 (使用上面的例子)。

插入惩罚:插入点球是一种特殊的惩罚,在这里并不重要

成本: 成本C是在特定点分页的总成本,TeX 在决定最佳分页点时会尽量减少页面成本。成本通常计算为

c=b+p+q

带着恶意b, 惩罚并插入惩罚如上所述。我写“通常”,因为真正的公式稍微复杂一些,并且是按照逐案方式定义的,当其中一个值为无限时,确实会处理特殊情况(参见 TeXbook 第 15 章第 111 页)。

球门高度:球门高度G是需要用垂直框列表填充的页面的期望高度。通常,G等于\textheight

总页数:页面总数是页面上所有垂直框的高度,并且还具有收缩/拉伸分量(由各个垂直框的拉伸/收缩分量产生)。

为了构建页面,TeX 会逐步向页面添加更多垂直框。在每个步骤中,TeX 都会计算成本C根据上面的公式。当页面总数大于目标高度G, 即使缩小到最小,即尽可能多地将内容挤到页面上。然后,TeX 从产生最低成本的步骤中选择一组垂直框。

日志文件的解释

第一个日志文件

现在,让我们看一下第一个 MWE 的日志文件(使用硬编码的“浮点数”和\clubpenalty=150):

%% goal height=550.0, max depth=5.0
% t=0.0 g=550.0 b=10000 p=0 c=100000#
% t=10.0 g=550.0 b=10000 p=0 c=100000#
% t=91.94444 g=550.0 b=10000 p=0 c=100000#
% t=192.34444 g=550.0 b=10000 p=0 c=100000#
% t=204.74443 plus 2.0 minus 2.0 g=550.0 b=10000 p=0 c=100000#
% t=286.68887 plus 2.0 minus 2.0 g=550.0 b=10000 p=0 c=100000#
% t=387.08887 plus 2.0 minus 2.0 g=550.0 b=10000 p=0 c=100000#
% t=414.03331 plus 5.0 minus 6.0 g=550.0 b=10000 p=150 c=100000#
% t=426.03331 plus 5.0 minus 6.0 g=550.0 b=10000 p=0 c=100000#
...
% t=534.03331 plus 6.0 minus 6.0 g=550.0 b=1881 p=0 c=1881#
% t=546.03331 plus 7.0 minus 6.0 g=550.0 b=18 p=150 c=168#
% t=558.03331 plus 7.0 minus 6.0 g=550.0 b=* p=0 c=*

球门高度G等于 550pt,因为这是\textheight。一开始,页面总由于顶部有两个“浮动”,页面总数迅速增加到 414.03331pt。从那里开始,页面总数以 12pt 为增量增加,因为这是 10pt 字体的基线跳跃。请注意,页面总数\textfloatsep由于和,已经获得了正 5.0pt 负 6.0pt 的拉伸/收缩性\floatsep

最后三行很重要。如果分页符放在第二段结束之后,尽管惩罚为零,但由于不良率较高,因此成本为 1881。让我们来算一下:目标高度等于 550pt,但当前页面总高度只有 534.03331。这导致缺失内容的增量为 15.96669pt,并且可拉伸性增加 6pt。这导致报告的不良率为 100*(15.96660pt/6pt)^3 = 1884。

如果分页符位于段落第一行之后,则只会导致坏度只有 18(使用相同公式)。因此,即使对俱乐部惩罚 150,总成本也会更低,TeX 决定接受俱乐部。

最后一行b=* 和 c=*只是说不可能在页面上再挤进一行。

第二个日志文件

前面的例子还告诉我们,对梅花的惩罚超过 1881-168 = 1713 就足以避免梅花。(这就是第二个 MWE 使用的原因\clubpenalty=2000。正如预期的那样,日志文件给出

% t=534.03331 plus 6.0 minus 6.0 g=550.0 b=1881 p=0 c=1881#
% t=546.03331 plus 7.0 minus 6.0 g=550.0 b=18 p=2000 c=2018
% t=558.03331 plus 7.0 minus 6.0 g=550.0 b=* p=0 c=*

更高的罚款导致总成本增加到 2018 年,并且 TeX 决定将分页符放在第二段之后。

第三个日志文件

像第三个示例那样使用实际浮点数会导致意外的观察结果:

%% goal height=152.51114, max depth=5.0
% t=0.0 g=152.51114 b=10000 p=0 c=100000#
% t=10.0 g=152.51114 b=10000 p=2000 c=100000#
% t=22.0 g=152.51114 b=10000 p=0 c=100000#
...
% t=130.0 plus 1.0 g=152.51114 b=10000 p=0 c=100000#
% t=142.0 plus 2.0 g=152.51114 b=10000 p=2000 c=100000#
% t=154.0 plus 2.0 g=152.51114 b=* p=0 c=*

目标高度下降到大约 152pt,即页面高度减去浮动元素占用的空间。更重要的是,页面整体失去了可拉伸性,因为\textfloatsep\floatsep不属于其中。这导致倒数第二行的分数非常高,因为分数的分母只有 2pt,而不是 7pt。

结束语

我知道,我可以设置\clubpenalty=10000完全禁止俱乐部。在这种情况下,TeX 会以不同的方式计算页面的成本。但是,使用“无限”值\clubpenalty可能会导致其他地方出现问题。

有趣的是,如果\clubpenalty=10000设置了,并且 TeX 被迫在第二段之后分页,则输出例程(此处未介绍)会再次考虑\textfloatsep和的可拉伸性\floatsep。我认为这非常不一致。

相关内容