我想定义一个命令,根据向量是处于显示模式还是内联数学模式来定义向量。到目前为止,我已经尝试过这个,但没有成功:
\newcommand{\ve}[1]{\ensuremath{%
\mathchoice{%
\begin{pmatrix}%
\StrSubstitute{#1}{,}{\\}%
\end{pmatrix}%
}{%
\left(\begin{smallmatrix}%
\StrSubstitute{#1}{,}{\\}%
\end{smallmatrix}\right)%
}{#1}{#1}%
}}
我希望能够$$\ve{1,2,x}$$
扩展到
\begin{pmatrix}
1\\2\\x
\end{pmatrix}
并$\ve{1,2,x}$
扩展至
\left(\begin{smallmatrix}
1\\2\\x
\end{smallmatrix}\right)
答案1
\displaystyle
区分内联和显示数学与区分\textstyle
和可能很棘手,因为align
类似环境的amsmath
内部使用$\displaystyle...$
。\ensuremath
此外,如果您在数学模式之外调用宏,您的定义将始终使用\textstyle
。在我看来(当然值得怀疑),\ensuremath
除非可爱的小猫和毛茸茸的兔子的生命取决于它,否则不应使用它;而且在这种情况下也不应该轻易使用它。
幸运的是,amsmath
提供了一个布尔值\if@display
,因此我们可以(滥用)使用它。我会加载mathtools
,这是的扩展amsmath
,其中除其他外,它已经定义了一个psmallmatrix
环境。
\documentclass{article}
\usepackage{mathtools}% loads amsmath
\makeatletter
\newcommand*{\ve}[1]{%
\begingroup
\if@display
\def\@tempa{{pmatrix}}
\else
\def\@tempa{{psmallmatrix}}
\fi
\expandafter\begin\@tempa
\@ve#1,\@@nil,
\expandafter\end\@tempa
\endgroup
}
\def\@ve#1,{\ifx\@@nil#1\else#1\\\expandafter\@ve\fi}
\makeatother
\begin{document}
\hsize=4cm % for the snapshot
\[
\ve{a}\ve{a,b}\ve{a,b,c}
\]
\begin{align*}
\ve{a}\ve{a,b}\ve{a,b,c}
\end{align*}
$\ve{a}\ve{a,b}\ve{a,b,c}$
\end{document}
编辑一个版本就像 egreg 的回答一样使用\mathchoice
。为了完整性,我还添加了一个行向量。这需要更多的技巧,因为\\
在列向量的末尾添加没有什么坏处(就像我的第一个代码一样),但是当你&
在行的末尾添加一个时就会出错。
\documentclass{article}
\usepackage{mathtools}
\makeatletter
\newcommand*{\cvector}[1]{\cr@vector{\\}{#1}}
\newcommand*{\rvector}[1]{\cr@vector{&}{#1}}
\newcommand*{\cr@vector}[2]{%
\mathchoice{\cr@@vector{#1}{#2}{}}%
{\cr@@vector{#1}{#2}{small}}%
{\cr@@vector{#1}{#2}{small}}%
{\cr@@vector{#1}{#2}{small}}%
}
\newcommand*{\cr@@vector}[3]{%
\def\@tempa{\gdef\@tempa{#1}}% first time does nothing, afterwards it's \\ or &
\def\@tempb##1,{\ifx\@@nil##1\else\@tempa##1\expandafter\@tempb\fi}%
\begin{p#3matrix}
\@tempb#2,\@@nil,
\end{p#3matrix}
}
\makeatother
\begin{document}
\hsize=5cm % for smaller snapshot
Display
\begin{align*}
\rvector{a,b,c} \cvector{a,b,c}
= \frac{\rvector{x,y} \cvector{u,v}}{\rvector{1,2,3}\cvector{4,5,6}}
\end{align*}
and inline $\rvector{a,b,c}$, $\cvector{a,b,c,d,e}$
\end{document}
可以在和\mathchoice
的定义中直接使用并省去一个中间宏,但我发现代码的可读性较差。\cvector
\rvector
答案2
这个想法很好。\ensuremath
当然,事实并非如此。
\documentclass[twocolumn]{article} % twocolumn is just to get a smaller picture
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\ve}{m}
{
\mathchoice
{\raymo_ve_display:n {#1}}
{\raymo_ve_inline:n {#1}}
{\raymo_ve_inline:n {#1}}
{\raymo_ve_inline:n {#1}}
}
\cs_new_protected:Nn \__raymo_ve_make:n
{
\seq_set_split:Nnn \l__raymo_ve_body_seq { , } { #1 }
\seq_use:Nn \l__raymo_ve_body_seq { \\ }
}
\cs_new_protected:Nn \raymo_ve_display:n
{
\begin{pmatrix}
\__raymo_ve_make:n { #1 }
\end{pmatrix}
}
\cs_new_protected:Nn \raymo_ve_inline:n
{
\left(\begin{smallmatrix}
\__raymo_ve_make:n { #1 }
\end{smallmatrix}\right)
}
\ExplSyntaxOff
\begin{document}
This is inline $\ve{1,2,x}$ and there is also a display
\[
\ve{1,2,x}
\]
\end{document}
如果您没有运行最新的 LaTeX 内核(2020-10-01),那么您需要\usepackage{xparse}
。
我发现expl3
比好多了xstrings
。
“优化”代码也支持行向量:
\documentclass[twocolumn]{article} % twocolumn is just to get a smaller picture
\usepackage{amsmath,mathtools}
\ExplSyntaxOn
\NewDocumentCommand{\gve}{mm}
{% #1 = c or r
\mathchoice
{\raymo_ve_build:nnn {#1}{#2}{}}
{\raymo_ve_build:nnn {#1}{#2}{small}}
{\raymo_ve_build:nnn {#1}{#2}{small}}
{\raymo_ve_build:nnn {#1}{#2}{small}}
}
\NewDocumentCommand{\ve}{m}{\gve{c}{#1}}
\NewDocumentCommand{\rve}{m}{\gve{r}{#1}}
\cs_new_protected:Nn \__raymo_ve_make:nn
{
\seq_set_split:Nnn \l__raymo_ve_body_seq { , } { #2 }
\seq_use:Nn \l__raymo_ve_body_seq { \str_case:nn {#1}{{c}{\\}{r}{&}} }
}
\cs_new_protected:Nn \raymo_ve_build:nnn
{
\begin{p#3matrix}
\__raymo_ve_make:nn { #1 } { #2 }
\end{p#3matrix}
}
\ExplSyntaxOff
\begin{document}
This is inline $\ve{1,2,x}\rve{1,2,x}$ and there is also a display
\[
\ve{1,2,x}\rve{1,2,x}
\]
\end{document}