TeX 子公式格式问题

TeX 子公式格式问题

众所周知,TeX 以自动化方式提供了出色的数学格式化功能。然而,有些地方存在明显的缺陷,人们要么接受,要么根据具体情况手动改进。

在这方面,最大的问题之一是 TeX 对子公式的处理(即括号组内的材料,例如和索引,以及任何顶层组)。TeX 总是将此类子公式设置为自然宽度,即使整个公式会受到严重的拉伸或收缩。例如,请考虑以下(不太合理)示例:

\documentclass{article}

\newlength\x

\begin{document}

\newcommand\formula{$ a+\mathbf{b+c}+d+e+f = \sum_{i=1}^{n-x-y-z} x_{i+j}$}

\settowidth\x{\formula}

\hbox to \x{\formula}    % natural width

\addtolength\x{-20pt}

\hbox to \x{\formula}   % now shrink it a lot

\addtolength\x{100pt}

\hbox to \x{\formula}   % now stretch a lot in the opposite direction

\end{document}

这里的公式在下标和上标中有许多明显的子公式,但为了说明起见,我还通过添加了一个子公式\mathbf。当然,以这种方式使用\mathbf是错误的!!!(它不应该应用于多个符号),但我相信你会在文档中找到它。无论如何,{b+c}在这里都会有同样的效果。现在你认为如果我们运行这个会发生什么?

这:

在此处输入图片描述

可以看出,当公式的其余部分受到拉伸或收缩时,自然“盒装”的子公式是非常错误的。

直到最近,TeX 引擎的后继者才解决了这个问题。随着 LuaTeX 开放了 TeX 的很多内部功能,我曾希望情况会有所不同。然而,在研究手册后,我的结论是,这个领域(至少到目前为止)尚未得到解决(或考虑)。

据我所知,在 LuaTeX 中解决此问题的唯一方法是使用回调mlist_to_hlist。然而,这实际上意味着替换整个数学排版算法,这当然可以解决问题,但是……但需要的不是这个(因为该算法的 99% 都接近完美),而是增加支持,而不仅仅是将子公式框在其自然宽度上。

文字太长了...下面是简短的问题:

  • 这个分析正确吗,还是我忽略了什么?
  • 以防有人知道:是否有计划调查子公式问题并最终为其提供支持?(它没有列在数学的“待办事项”中)

如果有人怀疑我谈论“这个子公式问题”就好像它是一个已知的东西……它是的,它早在E-TeX:未来 TeX 扩展指南当时进行了一些彻底的(如果不是激烈的)讨论。

答案1

看起来答案如下:

  • 该问题(在 TeX 原始程序中已经存在)尚未被包括 LuaTeX 在内的任何 TeX 后继者解决或处理。

LuaTeX 确实可以替代全部数学处理由私有代码完成,但这更像是“拆掉房子再建新房”,并没有真正保证。毕竟 TeX 的算法在大多数方面都非常棒。很遗憾,但也许可以理解,因为它需要拆开数学格式化程序的处理逻辑并重新组织它,才能改进其中的一小部分。

答案2

这是一个老问题,但我偶然发现了它,我认为现在可能有办法让它发挥作用,使用 luametatex 引擎*. 这是通过拆箱来完成的。(这不适用于平方根、分数或下标/上标。)我们首先看一下图片。

几个公式,一些解析

这里,

  1. 只需设置即可\hbox{word word $a + {\bf b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
  2. 设置为\hbox spread 4cm {word word $a + {\bf b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}。请注意,扩展在粗体部分不起作用。但它在围栏部分内起作用。如上所述,它不适用于平方根、分数或指数。
  3. 设置为\hbox spread 4cm {word word $a + \mathatom unpack \mathordinarycode {\bf b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}。因此,粗体部分也会被展开。它被解包,然后被打包为一个 ord。
  4. 设置为\hbox spread 4cm{word word $a + \mathbf{b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}。这表明解包和重新打包是在 中完成的\mathbf
  5. 设置为\hbox spread -2cm{word word $a + \mathbf{b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}。我们看到东西也可以打包在一起。
  6. 设置为\hbox spread 4cm{word word $a + \mathatom unpack leftclass \mathordinarycode rightclass \mathbinarycode {\bf c + d} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}。这不是我们想要的,但它表明,当我们重新打包时,我们可以说盒子在左边和右边的行为应该有所不同。在其他情况下可能有用。在这里,表现得像一个二进制的右边,使加号变成一个 ord,并且那里的间距是错误的。

拆包和重新打包的一个好处是,可以有多行公式,这些公式会在围栏内中断。示例(改编自这个老问题):

在栅栏内分成两条线的公式

此公式设置为

\defineformula[XYZ][
  split=text,
  textalign=slanted,
  spaceinbetween=.5\lineheight,
  strut=yes,
  distance=1em,
]

\startXYZformula[margin=3em]
s_{i}^{G}
=
\min 
\left\{
    \sqrt{
        \min\left[(x_{i}^{G} - x)^2, (w_{T} - x_{i}^{G} - x)^2\right] + y
        }
    ,\breakhere
    \sqrt{
        \min\left[(x_{i}^{G} - x)^2, (w_{T} - x_{i}^{G} - x)^2\right] 
        + 
        \min\left[(y_{i}^{G} - y)^2, (h_{T} - y_{i}^{G} - y)^2\right]
        }
\right\}
\stopXYZformula

*事实上,\mathbf{b + c}在 luatex 上下文中也可以工作。但解包机制是 luametatex 中的新机制。我没有安装 mkii,所以我不知道它是否也在 pdftex 上下文中工作。

答案3

有一种方法可以做到这一点,unicode-math因为 Unicode 数学中的粗体字母是相同字体的不同字母,而不是不同字体的字母:

\documentclass{article}

\usepackage{unicode-math}

\setmathfont{XITS Math}

\newlength\x

\begin{document}

\newcommand\formula{$ a+

相关内容