括号有很多种()
,,,,,等。在我使用的上下文中[]
,它们都已经具有固定的数学含义;因此我需要另一个。{}
||
<>
我使用的括号有两层,所以()
看起来像二项式系数或{}
像 Knuth 的斯特林集数符号等等。
我想要创建的新括号也是双层的,看起来(带有参数n
和k
)像
(n)
(k)
但是上部和下部之间没有间隙。在左侧,上部弧的最低点(
应接触下部弧的最高点(
。此设计镜像产生右侧的符号。
是否有希望利用(La)TeX工具实现这两个括号?
这是用绘画程序创建的符号。对于艺术家来说:欢迎使用 epsilon 的内涵。
编辑:看过前两个方案后,我注意到一个问题:双层的高度应该与二项式的高度相匹配(事实上,它们经常并排摆放是意料之中的事)。Manuel 的双层在直列式陈列柜中有点太大,在展示柜中又太小。Hagen 的双层在展示模式下不稳定。
两种解决方案并列:
第二次编辑:
Gustavo 的答案很棒,但 Manuel 的答案更简单,因此在某些情况下会更受欢迎。正如 Gustavo 指出的那样,命令必须在移动参数内受到保护。以下是一些测试代码:
\documentclass{scrartcl}
\usepackage{mathtools}
\usepackage{scalerel}
\usepackage{xparse}
\NewDocumentCommand{\stirling}{omm}
{%
\genfrac\{\}{0pt}{}{#2}{#3}%
\IfValueT{#1}{_{\!#1}}%
}
\makeatletter
\newcommand*\doubledecker[2]
{\mathpalette{\doubledeckeraux{#1}{#2}}\relax}
\newcommand*\doubledeckeraux[3]
{\vcenter{\offinterlineskip
\ialign{$\ifx\textstyle#3\scriptstyle
\else\ifx\scriptstyle#3\scriptscriptstyle
\fi\fi
\ifx\displaystyle#3\expandafter\bigl\fi(
\hfil##\hfil
\ifx\displaystyle#3\expandafter\bigl\fi)\m@th$\cr
\smash{#1}\cr
\smash{#2}\cr}}}
\makeatother
\begin{document}
This is how doubledecker looks inline: $\doubledecker{n}{k}$
\[
{\doubledecker{n}{k}}_m \ne \stirling[m]{n}{k}
\]
It needs another pair of $\{\}$ to display the index $m$ properly.
Here doubledecker has to be protected:
\begin{table}[h]\centering
\begin{tabular}[c]{c} $x$ \end{tabular}
\caption{ ${\protect \doubledecker{n}{k}}_m$ }
\end{table}
\end{document}
答案1
在过去的几天里,我突然对虚拟字体产生了浓厚的兴趣,我觉得,如果不提及使用虚拟字体的解决方案,对这个问题的讨论就有些不完整。毕竟,这几乎肯定是 Hagen von Eitzen 最初的想法(参见其他答案)。当然,已经提出的解决方案更直接、更容易实施,同时提供了出色的结果,因此,这一解决方案应该被视为一种附带的(和迂腐的)评论,只是为了详尽无遗而做出的。
展示
为了让您立即了解我们将要获得的结果,我将直接展示几个示例页面。我所做的第一次尝试是按照 Hagen 的建议,即反转括号的中间部分。当然,这只适用于一定大小的字体;对于较小的字体,我通过堆叠两个圆括号来构建所需的符号。这是我得到的结果:
显然不能令人满意:如果符号必须看起来像一对“双层”括号,那么它们在所有尺寸下都应该如此。因此,我想到了一个不同的解决方案,即用四个部分构建可扩展括号:顶部、底部和可重复部分,它们与(可扩展)圆括号中使用的对应部分相同,再加上一个中间部分,将圆括号的底部部分堆叠在相应的顶部部分上。我还对\big
和字符做了一些调整,分别借用和\Big
的括号,而不是缩小其中一个括号本身,结果如下:cmr6
cmr9
cmex10
好多了!但是,您会注意到,我还采取了似乎完全相反的步骤:在正常大小中,堆叠的括号已被左右“羽毛笔”符号(来自 ,TS1
或“文本伴侣”编码)取代,它们看起来就像是中心尖端反转的括号。我这样做的原因是我希望尽可能地重现标准符号字体的行为:虽然只有一个版本的“数学扩展”字体,即 ,但cmex10
“小”符号有多种字体和大小。使用有几十tc
种不同大小和样式的字体,我可以“免费”获得同样的多样性,而无需定义几十种虚拟字体。
[注:AMS 字体集还包括较小尺寸的“数学扩展”字体,即 、cmex7
和cmex8
。下面描述的我们从中派生虚拟字体的cmex9
过程也可以应用于这些字体,只需进行明显的调整,即可获得类似的虚拟字体,称为、和。然后,您可以按照与软件包类似的方式使用这些虚拟字体ddeckparex10
cmex10
ddeckparex7
ddeckparex8
ddeckparex9
安姆斯字体使用附加的 AMS 字体。我们将在下文中再次讨论这一点。
定义虚拟字体
请记住,已经有一个答案详细描述了这个过程。这使我可以保持以下评论相对简洁。
在这种情况下,虚拟字体必须从头开始定义(尽管可以从中复制大量摘录cmex10.pl
)。你该怎么做呢?嗯,这和你通常用计算机做的事情没太大区别:用面向人的编程语言编写源文件,然后让编译器将其转换成面向机器的形式。在这种情况下,“源文件”称为虚拟属性列表文件,“编译器”就是程序vptovf
(“虚拟属性列表到虚拟字体”的缩写)。要了解如何编写虚拟属性列表文件(扩展名.vpl
),你可以在终端提示符下键入texdoc vptovf
,然后阅读显示的文档的第 7-19 节。或者,如果你不介意,你也可以将以下代码保存到名为的文件中ddeckparex10.vpl
,并放在你选择的工作目录中:
(FAMILY DDKPAREX)
(CODINGSCHEME FONTSPECIFIC)
(DESIGNSIZE R 10.0)
(COMMENT DESIGNSIZE IS IN POINTS)
(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE)
(MAPFONT D 0 (FONTNAME cmex10))
(MAPFONT D 1 (FONTNAME cmr6) (FONTAT R .6)(FONTDSIZE R 6.0))
(MAPFONT D 2 (FONTNAME cmr9) (FONTAT R .9)(FONTDSIZE R 9.0))
(MAPFONT D 3 (FONTNAME cmex10)(FONTAT R .8333333))
(FONTDIMEN
(SLANT R 0.0)
(SPACE R 0.0)
(STRETCH R 0.0)
(SHRINK R 0.0)
(XHEIGHT R 0.430555)
(QUAD R 1.000003)
(EXTRASPACE R 0.0)
)
(CHARACTER H 10
(CHARWD R 0.4333284)
(CHARHT R 0.039999)
(CHARDP R 1.160013)
(NEXTLARGER H 12)
(MAP
(SELECTFONT D 1)
(MOVERIGHT R 0.0481476)(MOVEDOWN R 0.410001)
(PUSH)(SETCHAR O 50)(POP)
(MOVEDOWN R 0.600006)
(SETCHAR O 50)
)
)
(CHARACTER H 11
(CHARWD R 0.4333284)
(CHARHT R 0.039999)
(CHARDP R 1.160013)
(NEXTLARGER H 13)
(MAP
(SELECTFONT D 1)
(MOVERIGHT R 0.0962952)(MOVEDOWN R 0.410001)
(PUSH)(SETCHAR O 51)(POP)
(MOVEDOWN R 0.600006)
(SETCHAR O 51)
)
)
(CHARACTER H 12
(CHARWD R 0.41967345)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
(NEXTLARGER H 14)
(MAP
(SELECTFONT D 2)
(MOVERIGHT R 0.01998445)(MOVEDOWN R 0.6710001)
(PUSH)(SETCHAR O 50)(POP)
(MOVEDOWN R 0.900009)
(SETCHAR O 50)
)
)
(CHARACTER H 13
(CHARWD R 0.41967345)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
(NEXTLARGER H 15)
(MAP
(SELECTFONT D 2)
(MOVERIGHT R 0.0399689)(MOVEDOWN R 0.6710001)
(PUSH)(SETCHAR O 51)(POP)
(MOVEDOWN R 0.900009)
(SETCHAR O 51)
)
)
(CHARACTER H 14
(CHARWD R 0.458336)
(CHARHT R 0.039999)
(CHARDP R 2.360025)
(NEXTLARGER H 16)
(MAP
(PUSH)(SETCHAR O 0)(POP)
(MOVEDOWN R 1.200012)
(SETCHAR O 0)
)
)
(CHARACTER H 15
(CHARWD R 0.458336)
(CHARHT R 0.039999)
(CHARDP R 2.360025)
(NEXTLARGER H 17)
(MAP
(PUSH)(SETCHAR O 1)(POP)
(MOVEDOWN R 1.200012)
(SETCHAR O 1)
)
)
(CHARACTER H 16
(CHARWD R 0.597224)
(CHARHT R 0.039999)
(CHARDP R 2.9600315)
(NEXTLARGER H 18)
(MAP
(SELECTFONT D 3)
(MOVERIGHT R 0.0497687)(MOVEUP R 0.0199995)
(PUSH)(SETCHAR O 20)(POP)
(MOVEDOWN R 1.50001525)
(SETCHAR O 20)
)
)
(CHARACTER H 17
(CHARWD R 0.597224)
(CHARHT R 0.039999)
(CHARDP R 2.9600315)
(NEXTLARGER H 19)
(MAP
(SELECTFONT D 3)
(MOVERIGHT R 0.0497687)(MOVEUP R 0.0199995)
(PUSH)(SETCHAR O 21)(POP)
(MOVEDOWN R 1.50001525)
(SETCHAR O 21)
)
)
(CHARACTER H 18
(CHARWD R 0.597224)
(CHARHT R 0.039999)
(CHARDP R 3.560037)
(NEXTLARGER H 1A)
(MAP
(PUSH)(SETCHAR O 20)(POP)
(MOVEDOWN R 1.800018)
(SETCHAR O 20)
)
)
(CHARACTER H 19
(CHARWD R 0.597224)
(CHARHT R 0.039999)
(CHARDP R 3.560037)
(NEXTLARGER H 1B)
(MAP
(PUSH)(SETCHAR O 21)(POP)
(MOVEDOWN R 1.800018)
(SETCHAR O 21)
)
)
(CHARACTER H 1A
(CHARWD R 0.7361145)
(CHARHT R 0.039999)
(CHARDP R 4.760049)
(NEXTLARGER H 1C)
(MAP
(PUSH)(SETCHAR O 22)(POP)
(MOVEDOWN R 2.400024)
(SETCHAR O 22)
)
)
(CHARACTER H 1B
(CHARWD R 0.7361145)
(CHARHT R 0.039999)
(CHARDP R 4.760049)
(NEXTLARGER H 1D)
(MAP
(PUSH)(SETCHAR O 23)(POP)
(MOVEDOWN R 2.400024)
(SETCHAR O 23)
)
)
(CHARACTER H 1C
(CHARWD R 0.79167)
(CHARHT R 0.039999)
(CHARDP R 5.960062)
(NEXTLARGER H 30)
(MAP
(PUSH)(SETCHAR O 40)(POP)
(MOVEDOWN R 3.00003)
(SETCHAR O 40)
)
)
(CHARACTER H 1D
(CHARWD R 0.79167)
(CHARHT R 0.039999)
(CHARDP R 5.960062)
(NEXTLARGER H 31)
(MAP
(PUSH)(SETCHAR O 41)(POP)
(MOVEDOWN R 3.00003)
(SETCHAR O 41)
)
)
(CHARACTER H 30
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
(VARCHAR
(TOP H 30)
(MID H 38)
(BOT H 40)
(REP H 42)
)
)
(CHARACTER H 31
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
(VARCHAR
(TOP H 31)
(MID H 39)
(BOT H 41)
(REP H 43)
)
)
(CHARACTER H 38
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 3.560037)
(MAP
(PUSH)(SETCHAR H 40)(POP)
(MOVEDOWN R 1.800018)
(SETCHAR H 30)
)
)
(CHARACTER H 39
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 3.560037)
(MAP
(PUSH)(SETCHAR H 41)(POP)
(MOVEDOWN R 1.800018)
(SETCHAR H 31)
)
)
(CHARACTER H 40
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
)
(CHARACTER H 41
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
)
(CHARACTER H 42
(CHARWD R 0.875003)
(CHARDP R 0.600006)
)
(CHARACTER H 43
(CHARWD R 0.875003)
(CHARDP R 0.600006)
)
此后,通过键入以下内容“编译”虚拟字体
vptovf ddeckparex10.vpl
在命令行提示符下;这将始终在同一目录中生成,二ddeckparex10.tfm
分别称为和的面向机器的文件ddeckparex10.vf
,(pdf)TeX 从中获取排版新“双层”括号所需的所有信息。更准确地说,TeX 本身只需要文件来.tfm
完成排版工作,而文件.vf
要么被 DVI 预览器(或打印机驱动程序)用于学习如何显示(或打印)新符号,要么被 pdfTeX 用于在生成的 PDF 文件中包括适当的命令,这些命令从 CMEX10、CMR6 和 CMR9 字体开始重建新字形:只有这些字体才会真正包含在 PDF 中。同样的原则也适用于大多数 DVI 到某些字体的转换器:例如, dvips 将生成一个 PostScript 文件,其中仅包含对上述三种字体的引用(当然还有文档使用的所有其他字体)。
这些文件ddeckparex10.tfm
必须ddeckparex10.vf
保存在 (pdf)TeX(或 dvips 等)可以找到的地方。基本上有三种可能:
将它们都放在与
.tex
要编译的文件相同的目录中。这是一个快速简便的解决方案,但当然不能长期应用。将它们放在您的个人 texmf 树中。具体操作方法因系统而异。例如,对于我的 MacTeX 安装,这意味着:
将文件放在
ddeckparex10.tfm
某处~/Library/texmf/fonts/tfm/
(即,直接放在该目录内,或者放在其子目录内 - 或子子...子目录内);将文件放在(如上)
ddeckparex10.vf
下的某个位置 。~/Library/texmf/fonts/vf/
请注意,您可能必须在下创建必要的目录
~/Library/
。将它们放在本地机器范围的 texmf 树中。当然,为了做到这一点,您需要适当的访问权限。这也因系统而异;对我来说,这意味着:
将文件放在
ddeckparex10.tfm
下面的某个位置/usr/local/texlive/texmf-local/fonts/tfm/
;将文件放在
ddeckparex10.vf
下的某个位置/usr/local/texlive/texmf-local/fonts/vf/
。
至少使用 TeXLive,在此之后您必须
mktexlsr
从命令行发出命令,以便索引您的更改。
无论你选择哪种方式,你现在都可以奔跑
pdflatex nfssfont
生成新ddeckparex10
字体的字符表;如下所示:
通过这种方式,你还可以检查虚拟字体是否安装正确。顺便说一下,这是我第一次尝试的字符表:
支持虚拟字体的包
下面的代码
\NeedsTeXFormat{LaTeX2e}\relax % LaTeX2e is required!
\ProvidesPackage{ddkparex}
[2015/07/15 v0.01 (**development**)]
\@ifdefinable\@ddkp@saved@encoding{}
\let\@ddkp@saved@encoding=\encodingdefault
\RequirePackage[TS1]{fontenc}
\let\encodingdefault=\@ddkp@saved@encoding
\fontencoding\encodingdefault\selectfont
\DeclareFontFamily{U}{ddkparex}{\hyphenchar\font \m@ne}
\DeclareFontShape{U}{ddkparex}{m}{n}{<->ddeckparex10}{}
\DeclareSymbolFont{doubleDeckerParenthesesSmall}{TS1}{cmr} {m} {n}
\DeclareSymbolFont{doubleDeckerParenthesesLarge}{U} {ddkparex}{m} {n}
\SetSymbolFont{doubleDeckerParenthesesSmall}{bold}{TS1}{cmr}{b}{n}
\DeclareMathDelimiter{\lddparen}{\mathopen}
{doubleDeckerParenthesesSmall}{"A0}
{doubleDeckerParenthesesLarge}{"10}
\DeclareMathDelimiter{\rddparen}{\mathclose}
{doubleDeckerParenthesesSmall}{"A1}
{doubleDeckerParenthesesLarge}{"11}
实现了一个简单的包,叫做ddkparex,定义了两个新命令:
\lddparen
产生左(开)“双层”括号;\rddparen
产生一个右(右)“双层”括号。
\{
这两个命令的使用方式与其他产生分隔符的命令(如、 、 等)完全相同\rangle
,可以单独使用,也可以与\left
、\right
、\biggl
、\Biggr
、\genfrac
、 等一起使用……再简单不过了。
当然,上述代码应该保存在名为的文件中,该文件放在某个有效的 TeX 输入目录中,在最简单的情况下,该目录可以是包含要编译的文件ddkparex.sty
的同一目录。.tex
测试新命令
以下可编译示例将生成初始“展示”中显示的第二个示例页面:
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{ddkparex}
\begin{document}
First, let's have a look to the delimiters set in predetermined sizes.
The first two sizes, ``normal'' and \verb|\big|,
are adequate for in-line formulas,
and are exactly the same size of the other delimiters:
\( (x) \ne \lddparen x\rddparen \simeq
\bigl\lddparen x \bigr\rddparen \ne \bigl(x\bigr) \);
and \( \bigl\lddparen\!\tfrac{n}{k}\!\bigr\rddparen \) too.
Here is a display with \verb|\Big|, \verb|\bigg|, and \verb|\Bigg| delimiters,
in that order:
\begin{align*}
\Bigl\lddparen \frac{p}{b} \Bigr\rddparen
&\neq \Bigl( \frac{p}{b} \Bigr)
&
\biggl\lddparen \frac{p}{b} \biggr\rddparen
&\neq \biggl( \frac{p}{b} \biggr)
&
\Biggl\lddparen \frac{p}{b} \Biggr\rddparen
&\neq \Biggl( \frac{p}{b} \Biggr)
\end{align*}
Each variant is compared with a similarly-sized ordinary parenthesis. Note that
we have also included the fraction line to demonstrate that the delimiters are
vertically centered.
But delimiters of even \verb|\biggg|-er size are available too; they can be
accessed via \verb|\left| and \verb|\right|:
\begin{align*}
\left\lddparen
\begin{matrix}
1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 \\
\end{matrix}
\right\rddparen
&&
\left\lddparen
\begin{matrix}
1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 \\
\end{matrix}
\right\rddparen
\end{align*}
And here are the extensible ones:
\begin{align*}
\left\lddparen
\begin{matrix}
1 & 2 & 3 & 4 & 5 & 6 \\
2 & 0 & 0 & 0 & 0 & 0 \\
3 & 0 & 0 & 0 & 0 & 0 \\
4 & 0 & 0 & 0 & 0 & 0 \\
5 & 0 & 0 & 0 & 0 & 0 \\
6 & 0 & 0 & 0 & 0 & 0 \\
\end{matrix}
\right\rddparen
&&
\left\lddparen
\begin{matrix}
1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\
2 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
3 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
4 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
5 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
6 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
7 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
8 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
\end{matrix}
\right\rddparen
&&
\left\lddparen
\begin{matrix}
1\\2\\3\\4\\5\\6\\7\\8\\9\\0
\end{matrix}
\right\rddparen
\end{align*}
That's \emph{much} better!
Now, what about the ``quill'' symbols of the TS1~encoding, that the
\textsf{textcomp} package makes available with the commands \verb|\textlquill|
and \verb|\textrquill|? Using them, as we do, for the normal size of the
``double decker'' parentheses, the dissimilarity between the symbols in this
size and in the \verb|\big| one is evident; I'll show the two pairs again,
together with other kinds of parentheses as well:
\( \{x\} \neq \lddparen x\rddparen \simeq \bigl\lddparen x\bigr\rddparen
\neq \bigl(x\bigr) \simeq (x) \).
But the advantage is that, doing so, we have the symbol available in dozen of
size and face variants ``for free'': see, for example, the next two paragraphs.
{\Large\bfseries\boldmath A bolded formula:
\( (x) \ne \lddparen x\rddparen \).\par}
{\Large\bfseries The same formula in medium weight:
\( (x) \ne \lddparen x\rddparen \).\par}
In order to replicate this with a symbol constructed by us, we would need to
build dozens of virtual fonts (each containing only two characters).
{\Large\bfseries\boldmath But \( (x) \ne \lddparen x\rddparen \ne
\bigl\lddparen x\bigr\rddparen \ne \bigl(x\bigr) \).\par}
Indeed, the \texttt{cmex10} font hasn't got a bold variant.
\end{document}
通过查看此代码,您可以看到这两个新命令的使用方式与任何其他产生分隔符的命令完全相同,如上所述。
虚拟字体是如何定义的?
现在让我们检查一下该ddeckparex10.vpl
文件,看看里面放了什么内容以及新字符是如何定义的。 笔记: 本节相当长,仅针对感兴趣的读者。
如果您可以查阅字体指标的描述,您会发现更容易理解接下来的讨论:可以通过键入以下内容来生成cmex10
此描述的人性化形式(即该字体的属性列表或文件).pl
tftopl cmex10.tfm cmex10.pl
在命令行中。
开场白
(FAMILY DDKPAREX)
(CODINGSCHEME FONTSPECIFIC)
(DESIGNSIZE R 10.0)
(COMMENT DESIGNSIZE IS IN POINTS)
(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE)
(MAPFONT D 0 (FONTNAME cmex10))
(MAPFONT D 1 (FONTNAME cmr6) (FONTAT R .6)(FONTDSIZE R 6.0))
(MAPFONT D 2 (FONTNAME cmr9) (FONTAT R .9)(FONTDSIZE R 9.0))
(MAPFONT D 3 (FONTNAME cmex10)(FONTAT R .8333333))
是纯文本。首先,我们说这个文件定义了一个与常规名称 关联的字体系列DDKPAREX
;texmf 软件并不关心这个名称,实际上,在我们的上下文中,这个名称根本没有用处。无论如何,我们还指出,这种字体不遵循任何预定义的字体编码方案。相反,设计尺寸(10.0 打印机点)的规范很重要,因为文件中给出的几乎所有其他尺寸都是相对于设计尺寸的。但请注意,如果以不同的尺寸加载字体(很可能会发生),则后续的相对尺寸将乘以字体加载时的尺寸,不是按设计尺寸,从而提供适当的缩放比例;例如,如果您使用该选项排版文档12pt
,则将加载字体at 12pt
,并且所有字符尺寸以及制造字符本身的命令中给出的尺寸将参考比该选项使用的绝对尺寸大 1.2 倍的绝对尺寸10pt
。
随后的几行声明了用于构建虚拟字体的字符所取的字体,并为它们分配了数字,以便在后续中识别这些字体。
请注意,尽管\fondimen
此字体根本不需要任何参数,但我们还是定义了七个标准参数,以防我忘记某些东西。这些值只是从中复制而来cmex10.pl
。
现在我们来看看典型人物的定义:
(CHARACTER H 14
(CHARWD R 0.458336)
(CHARHT R 0.039999)
(CHARDP R 2.360025)
(NEXTLARGER H 16)
(MAP
(PUSH)(SETCHAR O 0)(POP)
(MOVEDOWN R 1.200012)
(SETCHAR O 0)
)
)
这是大小为 的左“双层”括号\bigg
,它\big
由从cmex10
(即我们的本地字体编号 0)中获取的两个左括号堆叠而成。此字符的宽度从\big
中的(左)括号的宽度复制而来cmex10
,而高度和深度只是\bigg
中的括号的高度和深度cmex10
;高度加深度等于 2.400024 个相对单位,也就是恰好是括号的相对高度加深度的两倍\big
。
然后,我们声明这个字符在这个字体中有一个后继,也就是大小的左“双层”括号\Bigg
。你可以检查它是否还有一个前任,与\Big
大小相对应。
接下来是构建虚拟角色的说明:这是我们实际进行构建的地方。由于我们的虚拟角色的高度恰好等于其最顶部部分的高度,因此我们可以简单地在当前参考点排版此部分(它是本地字体 0 中的字符 0,即cmex10
未缩放;无需指定字体编号,因为默认情况下隐含 0)。此后,我们返回参考点((PUSH)
/ (POP)
),向下移动高度加深度的一半,并排版另一个相同的字符:就这样。
其他字符需要稍微复杂一点的定义;例如,这是\big
正确的“双层”括号:
(CHARACTER H 11
(CHARWD R 0.4333284)
(CHARHT R 0.039999)
(CHARDP R 1.160013)
(NEXTLARGER H 13)
(MAP
(SELECTFONT D 1)
(MOVERIGHT R 0.0962952)(MOVEDOWN R 0.410001)
(PUSH)(SETCHAR O 51)(POP)
(MOVEDOWN R 0.600006)
(SETCHAR O 51)
)
)
此字符由取自 的两个右括号堆叠而成cmr6
。最初的想法是让此字符的高度和深度与\big
的括号一样高和一样深cmex10
,宽度与 的括号一样宽cmr6
。后者的宽度为 0.481476 乘以 6.0 点(请参阅 中字符八进制 51 的定义cmr6.pl
;您可以通过键入以下内容来生成此文件
tftopl cmr6.tfm cmr6.pl
在命令行中),即绝对尺寸为 2.888856 点,假设我们的字体以 10.0 点的设计大小加载,因此,字体cmr6
以 6.0 点的设计大小引用。因此,我们应该指定 0.2888856 的相对宽度。但是,这个宽度在打印时看起来太窄了,所以我决定将字符框加宽 50%,并在右侧(指向 d.-d. 括号的“内容”的那一侧)留出一些空间。
列表中的排版(MAP …)
说明考虑到了这种间隙,以及 (右) 括号的高度cmr6
为 0.75 个相对单位(再次参见cmr6.pl
,字符八进制 51):选择字体编号 1 后,我们首先从参考点向右向下移动适当的量(在计算垂直偏移时,不要忘记在两种字体使用的不同单位之间进行转换,即 10.0 点和 6.0 点),然后我们按上述方式进行。
对两个\Big
字符 12 和 13(十六进制)也进行了类似的调整。
我们的虚拟字体中的字符被组织成两个相似的字形系列,这些字形的大小逐渐增大:对于左 d.-d. 括号,该系列从字符位置 10 开始,一直延伸到位置 12、14、16、18、1A、1C 和 30(数字采用十六进制表示法);对于右括号,另一个系列以类似的方式从位置 11 延伸到位置 31。两个系列(30 和 31)的最后字符都是可扩展的:例如,字符 30 指定为
(CHARACTER H 30
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 1.760019)
(VARCHAR
(TOP H 30)
(MID H 38)
(BOT H 40)
(REP H 42)
)
)
该(VARCHAR …)
列表精确地表明,字符 30(十六进制)是一个可扩展字符,由四个部分组成:位于插槽 30 本身的顶部部分、位于插槽 38 的中间部分、位于插槽 40 的底部部分以及位于插槽 42 的可重复部分(所有十六进制数字)。除中间部分外,所有部分都映射到字体 0 中具有相同位置的字符,即cmex10
(这是默认映射,因此(MAP …)
不需要在其中任何一个中包含列表)具有相同的宽度、高度和深度;它们的位置已被选择,以便每个部分都映射到可扩展左括号的正确部分。相反,中间部分的定义如下:
(CHARACTER H 38
(CHARWD R 0.875003)
(CHARHT R 0.039999)
(CHARDP R 3.560037)
(MAP
(PUSH)(SETCHAR H 40)(POP)
(MOVEDOWN R 1.800018)
(SETCHAR H 30)
)
)
这意味着一个角色构造堆叠底部同一可扩展括号的一部分顶部部件,与底部部件一样宽和一样高,并且深度的计算方式使得该字符的高度加深度等于底部部件的高度加深度与顶部部件的高度加深度之和(即 1.800018 + 1.800018 = 3.600036)。列表使用(MAP …)
上述相同技术精确指定了此构造。
其它可扩展字符(十六进制31)类似。
添加 AMS 尺寸
如果你觉得真的对此解决方案充满热情,您现在可以重复整个过程三多次从AMS 提供的cmex9
、cmex8
和字体(加上一些合适的字体大小,可能经过缩放)中派生出另外三种与我们的 类似的虚拟字体,但设计大小分别为 9、8 和 7 点。当然,这些额外的虚拟字体应该命名为 、和。在此之后,您可以调整中包含的字体系列的定义cmex7
cmr
ddeckparex10
ddeckparex9
ddeckparex8
ddeckparex7
ddkparex
ddkparex包,以便它加载这些新的(虚拟)字体以适应某些尺寸范围,而不是缩小字体ddeckparex10
。它足以模仿安姆斯字体包对cmex
字体的作用:只需替换一行
\DeclareFontShape{U}{ddkparex}{m}{n}{<->ddeckparex10}{}
和
\DeclareFontShape{U}{ddkparex}{m}{n}{
<-7.5>ddeckparex7
<7.5-8.5>ddeckparex8
<8.5-9.5>ddeckparex9
<9.5-> ddeckparex10
}{}
在文件中ddkparex.sty
。
这是一个非常长的答案!(我说它会很“迂腐”。)但这个问题实际上要求涉及虚拟字体的答案:我想说这正是人们为了说明虚拟字体通常可用于什么而发明的那种问题。
答案2
我发现我原本想做的事情意味着要摆弄.tfm
文件之类的东西。但多亏了另一个 texSE 问题 (如何创建一个新的可扩展符号?)我想到了这个:
\documentclass{scrartcl}
\usepackage{scalerel}% http://ctan.org/pkg/scalerel
\newcommand*\doubledecker[2]{
\scaleleftright{\leftdoubleparens}{{\mathstrut #1 \atop \mathstrut #2}}{\rightdoubleparens}
}
\newcommand\leftdoubleparens{\vbox{\hbox{(}\vskip-2.85pt\hbox{(}}}
\newcommand\rightdoubleparens{\vbox{\hbox{)}\vskip-2.85pt\hbox{)}}}
\newcommand\test[2]{
\[
\frac{#1}{#2}
{#1\choose #2}
\doubledecker{#1}{#2}
\]
}
\begin{document}
\test{a}{b}
\test{pm}{bq}
\test{e^{2\pi i}}{x}
\test{e^{2\pi i}}{\sum_{n=1}^\infty\frac1{n^2}}
\test{e^{2\pi i}}{\displaystyle\sum_{n=1}^\infty\frac1{n^2}}
\end{document}
您可能想尝试一下\leftdoubleparens
和的定义\rightdoubleparens
。魔术常数-2.85pt
经过实验调整,使得两个括号的尖端重叠(准确吗?)。这可能取决于使用的字体,最好通过排版像 这样的怪物来检查\doubledecker{\vrule height 100 pt}{\vrule height 100 pt}$
。请注意,在某些情况下,双括号的中间尖端可能不会准确指向“分子”和“分母”之间(而且似乎\choose
在这些情况下也开始出现问题)
答案3
第一种方法
\documentclass{scrartcl}
\usepackage{mathtools}
\makeatletter
\newcommand*\doubledecker[2]
{\mathord{\mathpalette{\doubledeckeraux{#1}{#2}}\relax}}
\newcommand*\doubledeckeraux[3]
{\vcenter{\offinterlineskip
\ialign{$\ifx\textstyle#3\scriptstyle
\else\ifx\scriptstyle#3\scriptscriptstyle
\fi\fi
(\hfil##\hfil)\m@th$\cr
#1\cr
#2\cr}}}
\makeatother
\begin{document}
$\frac{a}{b}\doubledecker{a}{b}$
$\displaystyle\frac{a}{b}\doubledecker{m}{n}$
\end{document}
这是关于获得与 相同的高度的新请求的新定义\binom
,在文本样式中,我认为即使它看起来大一点也不会带来问题,因为高度是相同的
\makeatletter
\newcommand*\doubledecker[2]
{\mathpalette{\doubledeckeraux{#1}{#2}}\relax}
\newcommand*\doubledeckeraux[3]
{\vcenter{\offinterlineskip
\ialign{$\ifx\textstyle#3\scriptstyle
\else\ifx\scriptstyle#3\scriptscriptstyle
\fi\fi
\ifx\displaystyle#3\expandafter\bigl\fi(
\hfil##\hfil
\ifx\displaystyle#3\expandafter\bigl\fi)\m@th$\cr
\smash{#1}\cr
\smash{#2}\cr}}}
\makeatother
不过,为了安全起见,如果您要输入任何类型的非字母等,最安全的方法可能是使用包scalerel
,正如另一个答案所建议的那样。此解决方案具有很好的输出效果,即给出与每行对齐的括号,但如果行有点大,包含太多数学运算,括号就会变得疯狂。
答案4
使用stackengine
。我在比较中注意到,即使指定了,amsmath
宏\binom
也会进入(这是一个错误还是功能?)我已经在我的实现中模仿了这一点。\scriptscriptstyle
\scriptstyle
\documentclass{article}
\usepackage{stackengine,scalerel}
\newcommand\UPP[1]{\raisebox{\dimexpr1.5pt-2.7\LMpt}{#1}}
\newcommand\DPP[1]{\raisebox{\dimexpr.2pt+.1\LMpt}{#1}}
\makeatletter
\newcommand\doubledecker[2]{\ThisStyle{\ensurestackMath{%
\savestack\ddtmp{\stackanchor{\SavedStyle#1}{\SavedStyle#2}}%
\savestack\ddbinom{$\SavedStyle\binom{X}{X}$}%
\savestack\Lparen{%
$\scaleto{(}{\dimexpr.5\ht\ddbinomcontent+.5\dp\ddbinomcontent}$}%
\savestack\Rparen{%
$\scaleto{)}{\dimexpr.5\ht\ddbinomcontent+.5\dp\ddbinomcontent}$}%
\def\@mstyleD{\textstyle}% NO \displaystyle INSIDE \binom
\def\@mstyleS{\scriptscriptstyle}% NO \scriptstyle INSIDE \binom
\vcenter{\hbox{%
\stackunder[0pt]{\UPP{\Lparen}\smash{\makebox[\wd\ddtmpcontent]{$\SavedStyle#1$}}\UPP{\Rparen}}%
{\DPP{\Lparen}\smash{\makebox[\wd\ddtmpcontent]{$\SavedStyle#2$}}\DPP{\Rparen}}%
}}}}}
\makeatother
\usepackage{amsmath}% FOR COMPARISON
\begin{document}
\[ \binom{n}{m} \doubledecker{n}{m}\quad
\binom{\sum x^2}{y_{y_y}} \doubledecker{\sum x^2}{y_{y_y}}\]
\[ \scriptstyle\binom{n}{m} \doubledecker{n}{m}\quad
\binom{\sum x^2}{y_y} \doubledecker{\sum x^2}{y_y}\]
\[ \scriptscriptstyle\binom{n}{m} \doubledecker{n}{m}\quad
\binom{\sum x^2}{y_y} \doubledecker{\sum x^2}{y_y}\]
\end{document}