数学模式中嵌套 \text 的必要性,以实现正确的基于 \mathchoice 的缩放

数学模式中嵌套 \text 的必要性,以实现正确的基于 \mathchoice 的缩放

快速摘要: \text\text可用于确保根据正确的数学样式进行适当的缩放。究竟何时应将其用于此目的?为此目的需要嵌套调用吗?


amsmath\text 包括\mathchoice,人们可能遇到过形式为\mathpalette

何时可能需要使用\text解释这里。 的一个高级用例\text是确保数学模式中嵌入的某种文本框内的文本能够正确缩放。一个具体的例子是我对 180° 旋转的 iota ( ) 的定义,它可以用来表示唯一性选择器(此处\trnupiota):

\documentclass{article}
\usepackage{upgreek} % for \upiota
\usepackage{rotating} % for \rotatebox
\usepackage{amsmath} % for \text
\usepackage{accsupp} % for the right Unicode codepoint

\newcommand*{\trnupiota}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \text{\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}
\newcommand*{\trnupiotaNoText}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % without \text
  \EndAccSupp{}}


\begin{document}

\(\trnupiota x \,(x \ge 0 \wedge x^{2} = 2)\)
  % denotes the square root of 2, which is by convention non-negative

\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly

\(\trnupiotaNoText + a_{\trnupiotaNoText + a_{\trnupiotaNoText}}\)
  % doesn't scale correctly

\end{document}

(也可以使用普通的 iota: ι;约定不同。)整个第一行表示“唯一的x非负数,并且2平方相等”:

唯一性选择器

正如我们所见,\trnupiota在不同的数学风格中,比例是正确的,而\text-less\trnupiotaNoText则不正确。

正如评论主题中解释的那样答案链接在上面\text可能会很慢,尤其是在嵌套时:相关材料排版 4 次(因此该材料的时间增加了四倍)。编译时间增加 4 倍通常只会影响微小的公式块,但了解一些规则会很有用,这些规则决定了我们何时可以安全地不是使用\text

我们还知道(这在同一个评论线程中解释过),当加载amstext或时,以下文本宏已经包含了以下机制:,,,,,,,,,,,,。也就是说,对于那些我们不需要在它们的调用周围添加额外的内容。amsmath\text\textrm\textsf\texttt\textnormal\textbf\textmd\textit\textsl\textsc\textup\emph\text

让我们弄清楚\text在数学模式中我们何时真正需要。在我的例子中,\rotatebox需要\text。常用框\raisebox需要\text。上一段中的文本宏已经包含\text;额外的\text会浪费计算资源。但是像下面这样的构造呢?

  • \raise0.5ex\hbox{MATERIAL}
  • 我有一个定义为 的宏\mathbin{\text{\ooalign{...\raise0.1ex\hbox{\(...\raisebox{...}{\scalebox{...}{\(MATERIAL\)}}...\)}...}}}。(不要问为什么;这与我的使用\ooalign以及定义之间的一致性有关。)\(...\)在我的宏中第一次使用 有效地创建了一个\textstyle(与调用宏的最外层数学样式无关;对吗?),因此以下内容\raisebox不会引起任何问题,也不需要另一个\text

如何描述需要使用\text数学模式的环境?我正在寻找类似这样的答案:“所有基于 TeX 基元 X、Y、Z 的框,如果它们处于非\textstyle数学模式中”?还有什么需要了解的?

答案1

我同意对嵌套 s 的担忧\mathchoice是真实存在的(我见过一些不涉及\text嵌套 s 重要性的案例,例如,\widebar 存在严重问题,以及答案后缀的“重要说明”)。

但是,我并没有问“我什么时候‘需要’ \text?”,而是将其视为“我如何才能\text为我工作?”在我的 MWE 中,我提出的方法是在序言中,而下面的代码重新定义\hrulefill纯粹是为了对问题进行诊断检查。

\mathchoice当我怀疑嵌套导致编译速度变慢时,我发现有用的方法是(在宏的用户端)开发一种本地“修复”数学样式的方法,从而避免\mathchoice扩展。底层定义(在本例中为\trnupiota)必须保持通用,能够处理任何数学样式。但最终用户通常会知道其使用实例的数学样式是什么。在这些情况下,并且仅当编译速度成为问题时,为最终用户提供 的短路才有用\mathchoice

因此,对于 的情况\text,我通过对 的局部重新定义 , ,和来强制显示\Dtext、文本、脚本或脚本脚本样式中的行为。\Ttext\Stext\stext\mathchoice

我在您的定义中实现这一点的方法\trnupiota是使用可选参数。留空时,\text将调用常规。但是,如果使用[D][T][S]或选项,则会调用[s]的可选版本。\text


\hrulefill在 MWE之后,我诊断性地重新定义\mathchoice以计算要制作的框数,然后再选择要排版的最后一个框。正如所展示的,每次您可以提前修复特定调用的数学样式\text(通常从问题的上下文中得知),为该调用创建的框数就会从 4 个减少到 1 个。

\documentclass{article}
\usepackage{upgreek} % for \upiota
\usepackage{rotating} % for \rotatebox
\usepackage{amsmath} % for \text
\usepackage{accsupp} % for the right Unicode codepoint

\newcommand*{\trnupiota}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \text{\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}

\def\Dtext#1{{\renewcommand\mathchoice[4]{##1}\text{#1}}}% FORCE \displaystyle
\def\Ttext#1{{\renewcommand\mathchoice[4]{##2}\text{#1}}}% FORCE \textstyle
\def\Stext#1{{\renewcommand\mathchoice[4]{##3}\text{#1}}}% FORCE \scriptstyle
\def\stext#1{{\renewcommand\mathchoice[4]{##4}\text{#1}}}% FORCE \scriptscriptstyle

\begin{document}

\(\trnupiota x \,(x \ge 0 \wedge x^{2} = 2)\)
  % denotes the square root of 2, which is by convention non-negative

\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly

The following redefinition of the macro \verb|\trnupiota| will allow an 
optional  argument D, T, S, or s to force the mathstyle of \verb|\text|, 
thus saving on the inefficiency of \verb|\mathchoice|.

\renewcommand*{\trnupiota}[1][]{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \csname#1text\endcsname%
    {\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}

\(\trnupiota[D] + a_{\trnupiota[S] + a_{\trnupiota[s]}}\)
  % scales correctly

\hrulefill

To see how this works, let's have \verb|\mathchoice| count the boxes.

\let\svmathchoice\mathchoice
\newcounter{bxcnt}
\renewcommand\mathchoice[4]{\svmathchoice%
  {\stepcounter{bxcnt}#1}%
  {\stepcounter{bxcnt}#2}%
  {\stepcounter{bxcnt}#3}%
  {\stepcounter{bxcnt}#4}%
}
\def\Dtext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##1}\text{#1}}}
\def\Ttext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##2}\text{#1}}}
\def\Stext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##3}\text{#1}}}
\def\stext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##4}\text{#1}}} 
\newcommand\boxcount{\par\thebxcnt\ mathchoice boxes made\setcounter{bxcnt}{0}}


\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly
\boxcount

\(\trnupiota + a_{\trnupiota + a_{\trnupiota[s]}}\)
\boxcount

\(\trnupiota + a_{\trnupiota[S] + a_{\trnupiota[s]}}\)
\boxcount

\(\trnupiota[D] + a_{\trnupiota[S] + a_{\trnupiota[s]}}\)
\boxcount
\end{document}

在此处输入图片描述

在 之后的第一个例子中\hrulefill,三个\trnupiota实例中的每一个都被装箱四次,从而产生了 4+4+4=12 个箱子。当在第二个例子中将其中一个实例硬连线时,箱子的数量为 4+4+1=9 个箱子;对于第三个例子,箱子的数量为 4+1+1=6 个箱子;而在最后一个例子中,箱子的数量为 1+1+1=3 个。

答案2

正如命令名称所暗示的,\text它是用于需要适应当前数学上下文的自然语言文本。按照这里建议的方式将其用作纯数学上下文是滥用命令,这使得它效率低下并且不能保证产生正确的字体大小。

\text{hello $x+y$}如果在上标上下文中使用,则将获得 latex 将使用的设置\scriptsize hello $x+y$,这意味着(第一次使用时)LaTeX 需要为该文本大小设置所有数学字体,但更重要的是$x+y$将设置\textfont为文本大小的数学大小\scriptsize。 的大小和为该文本字体大小声明的数学字体的大小都是由正在使用的类设置的任意大小,并且可能与当前文本大小的\scriptsize大小不同。\scriptfont

如果您需要使用hello由外部数学表达式决定的大小来设置文本格式,那么这\text是一个不错的选择。

但是,如果您只想使用包含当前\scriptfont大小的数学集的框,最好\mathchoice, passing in the current style, so在上标中使用 \scriptstyle`。

latex 中的宏\mathpalette继承自 plain,正是为此目的而设计的。它调用\mathcoice原始宏,将当前样式作为第一个参数传递。第二个参数通常是用户提供的参数,例如\phantom或的参数\root,但此处定义的命令不带参数,因此我传入{}

在此处输入图片描述

\documentclass{article}
\usepackage{upgreek} % for \upiota
\usepackage{rotating} % for \rotatebox
\usepackage{amsmath} % for \text
\usepackage{accsupp} % for the right Unicode codepoint

\newcommand*{\trnupiota}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \text{\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}
\newcommand*{\trnupiotaNoText}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % without \text
  \EndAccSupp{}}
\newcommand*{\trnupiotamp}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \mathpalette\trnupiotampx{}%
  \EndAccSupp{}}}

\newcommand*\trnupiotampx[1]{\raisebox{\depth}{\rotatebox{180}{\(#1\upiota\)}}}% % with \text
\begin{document}

\(\trnupiota x \,(x \ge 0 \wedge x^{2} = 2)\)
  % denotes the square root of 2, which is by convention non-negative

\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly

\(\trnupiotaNoText + a_{\trnupiotaNoText + a_{\trnupiotaNoText}}\)
  % doesn't scale correctly

\(\trnupiotamp + a_{\trnupiota + a_{\trnupiota}}\)
  % scales even more correctly

\end{document}

相关内容