我一直在寻找一种解决方案,将一系列方程式排版成两列等宽,两列垂直对齐,没有多余的空间。具体来说,我正在寻找一种解决方案,我可以这样做:
\begin{envthatiwant}{2}
a &= a \\
b &= b \\
c &= c \\
d &= d
\end{envthatiwant}
它会自动分成两列(如果行数为奇数,并且它足够智能,能够找出在 c(在 abcde 中)处中断的方法,则可以获得加分)。
我尝试阅读其他解决方案,但尚未找到令人满意的解决方案。下面是 MWE 代码和五个案例。
第一种情况比较简单,只使用了multicols
+ noindent
。间距对于外行人来说是相当随机和不可预测的,所以这样的解决方案远非我想要的。
第二种情况是将align
s 放在 multicols 中,并将noindent
s(我也想知道是否有办法自动放置它们)放在特定环境的开头。然而,这里的问题是这些
第三种情况是使用与我想要的解决方案类似的代码,但是显然效果不太好。
第四种情况是使用aligned
,这是我在之前的解决方案中看到的。由于 参数,所有内容都是垂直对齐的,因此这有点接近[t]
。但是,它不会像多列的情况那样将其分成两列等长(参见情况 1、2)。当然,我可以添加\qquad
s 或其他任何东西,但每次都需要一些手动干预。
第五种情况滥用了align
。这最接近我想要的,但从代码角度来看,这是一场噩梦,因为我必须提前计划并考虑要放入多少个方程式。如果我想在c
和之间添加一个方程式d
,那么我必须手动将所有内容向下移动一步。
\documentclass{article}
\usepackage{amsmath}
\usepackage{multicol}
\begin{document}
\noindent Hello! This is Case 1.
\begin{multicols}{2} \noindent
$$a = a$$
$$b = b$$
\\ \noindent
$$c = c$$
$$d = d$$
\end{multicols}
\noindent Hello! This is Case 2.
\begin{multicols}{2} \noindent
\begin{align*}
a &= a \\
b &= b
\end{align*} \noindent
\begin{align*}
c &= c \\
d &= d
\end{align*}
\end{multicols}
\noindent Hello! This is Case 3.
\begin{multicols}{2}
\begin{align*}
a &= a \\
b &= b \\
c &= c \\
d &= d
\end{align*}
\end{multicols}
\noindent Hello! This is Case 4.
$$
\begin{aligned}[t]
a &= a \\
b &= b
\end{aligned} \qquad %if you want
\begin{aligned}[t]
c &= c \\
d &= d
\end{aligned}
$$
\noindent Hello! This is Case 5.
\begin{align*}
a &= a & c &= c \\
b &= b & d &= d
\end{align*}
答案1
此代码将存储行数并将数字四舍五入为#1
(所需列数)的倍数。接下来,使用嵌套循环,它获取条目数
1+0*n, 1+1*n, ..., 1+(#1-1)*n
2+0*n, 1+1*n, ..., 2+(#1-1)*n
...
n+0*n, n+1*n, ..., n+(#1-1)*n
其中n
是最终的行数,存储每个新行,并用 分隔项目&
。
最后它给出结果,各行之间用 分隔\\
。
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{columnalign}{m b}
{% #1 = number of columns, #2 = body
\guissmo_columnalign:nn { #1 } { #2 }
}
{\ignorespacesafterend}
\seq_new:N \l__guissmo_columnalign_in_seq
\seq_new:N \l__guissmo_columnalign_out_seq
\seq_new:N \l__guissmo_columnalign_temp_seq
\int_new:N \l__guissmo_columnalign_rows_int
\cs_new_protected:Nn \guissmo_columnalign:nn
{
% store the rows in the sequence
\seq_set_split:Nnn \l__guissmo_columnalign_in_seq { \\ } { #2 }
\int_compare:nF { \int_mod:nn { \seq_count:N \l__guissmo_columnalign_in_seq } { #1 } = 0 }
{% number of rows not a multiple of #1, add empty entries
\prg_replicate:nn { #1 - \int_mod:nn { \seq_count:N \l__guissmo_columnalign_in_seq } { #1 } }
{
\seq_put_right:Nn \l__guissmo_columnalign_in_seq {}
}
}
\seq_clear:N \l__guissmo_columnalign_out_seq
\int_set:Nn \l__guissmo_columnalign_rows_int
{ \int_div_truncate:nn { \seq_count:N \l__guissmo_columnalign_in_seq } { #1 } }
\int_step_inline:nn { \l__guissmo_columnalign_rows_int }
{% clear the temporary sequence
\seq_clear:N \l__guissmo_columnalign_temp_seq
\int_step_inline:nnn { 0 } { #1 - 1 }
{
\seq_put_right:Nx \l__guissmo_columnalign_temp_seq
{
\seq_item:Nn \l__guissmo_columnalign_in_seq
{ ##1 + \l__guissmo_columnalign_rows_int * ####1 }
}
}
\seq_put_right:Nx \l__guissmo_columnalign_out_seq
{
\seq_use:Nn \l__guissmo_columnalign_temp_seq { & }
}
}
% now \l__guissmo_columnalign_out_seq contains the new rows
\begin{align*}
\seq_use:Nn \l__guissmo_columnalign_out_seq { \\ }
\end{align*}
}
\ExplSyntaxOff
\begin{document}
\begin{columnalign}{2}
a&=a \\
b&=b \\
c&=c \\
d&=d \\
e&=e
\end{columnalign}
\begin{columnalign}{3}
a&=a \\
b&=b \\
c&=c \\
d&=d \\
e&=e
\end{columnalign}
\begin{columnalign}{3}
a&=a \\
b&=b \\
c&=c \\
d&=d \\
e&=e \\
f&=f
\end{columnalign}
\end{document}
在此版本中,您还可以为块添加单个方程编号。新的可选参数设置列间距。
\documentclass{article}
\usepackage{amsmath,array}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{columnalign}{O{3em} m b}
{% #1 = column spacing, #2 = number of columns, #3 = body
\guissmo_columnalign:nnnn { #1 } { #2 } { #3 } { }
}
{}
\NewDocumentEnvironment{columnalign*}{O{3em} m b}
{% #1 = column spacing, #2 = number of columns, #3 = body
\guissmo_columnalign:nnnn { #1 } { #2 } { #3 } { * }
}
{}
\seq_new:N \l__guissmo_columnalign_in_seq
\seq_new:N \l__guissmo_columnalign_out_seq
\seq_new:N \l__guissmo_columnalign_temp_seq
\int_new:N \l__guissmo_columnalign_rows_int
\cs_new_protected:Nn \guissmo_columnalign:nnnn
{
\__guissmo_split:nnn { #1 } { #2 } { #3 }
% now \l__guissmo_columnalign_out_seq contains the new rows
\begin{equation#4}
\begin{alignedat}{3}
\seq_use:Nn \l__guissmo_columnalign_out_seq { \\ }
\end{alignedat}
\end{equation#4}
}
\cs_new_protected:Nn \__guissmo_split:nnn
{
% store the rows in the sequence
\seq_set_split:Nnn \l__guissmo_columnalign_in_seq { \\ } { #3 }
\int_compare:nF { \int_mod:nn { \seq_count:N \l__guissmo_columnalign_in_seq } { #2 } = 0 }
{% number of rows not a multiple of #2, add empty entries
\prg_replicate:nn { #2 - \int_mod:nn { \seq_count:N \l__guissmo_columnalign_in_seq } { #2 } }
{
\seq_put_right:Nn \l__guissmo_columnalign_in_seq {}
}
}
\seq_clear:N \l__guissmo_columnalign_out_seq
\int_set:Nn \l__guissmo_columnalign_rows_int
{ \int_div_truncate:nn { \seq_count:N \l__guissmo_columnalign_in_seq } { #2 } }
\int_step_inline:nn { \l__guissmo_columnalign_rows_int }
{% clear the temporary sequence
\seq_clear:N \l__guissmo_columnalign_temp_seq
\int_step_inline:nnn { 0 } { #2 - 1 }
{
\seq_put_right:Nx \l__guissmo_columnalign_temp_seq
{
\seq_item:Nn \l__guissmo_columnalign_in_seq
{ ##1 + \l__guissmo_columnalign_rows_int * ####1 }
}
}
\seq_put_right:Nx \l__guissmo_columnalign_out_seq
{
\seq_use:Nn \l__guissmo_columnalign_temp_seq { &\hspace{#1} }
}
}
}
\ExplSyntaxOff
\begin{document}
\begin{columnalign}{2}
a&=a \\
b&=b \\
c&=c \\
d&=d \\
e&=e
\end{columnalign}
\begin{columnalign}[2em]{3}
a&=a \\
b&=b \\
c&=c \\
d&=d \\
e&=e
\end{columnalign}
\begin{columnalign*}{3}
a&=a \\
b&=bbbb \\
c&=ccc \\
d&=d \\
e&=e \\
f&=f
\end{columnalign*}
\end{document}