有人可以构建以下矢量操作的宏吗?
1) Example data: \def\a{(5,3,0)}
\def\b{(5,1,6)}
\def\A{(1,0,1\\0,2,0\\0,0,3)}
2) Vector addition: $\a+\b$ returns (10,4,6)
3) Vector subtraction: $\a-\b$ returns (0,2,-6)
4) Vector matrix multiplication: $\A*\a$ returns (5,6,0)
感谢 David 的代码,我扩展了以下内容:1) 向量加法、2) 向量减法、3) 向量乘法、4) 向量除法。我要做的是将代码扩展为 5) \car 和 \cdr 以进行列表处理。以下是第一步。
\documentclass{article}
\makeatletter
%main macros
\def\rvecadd#1#2{\edef\tmp{\noexpand\@rvecadd+#1,\relax#2,\relax}\tmp}
\def\rvecsub#1#2{\edef\tmp{\noexpand\@rvecadd-#1,\relax#2,\relax}\tmp}
\def\rvecmul#1#2{\edef\tmp{\noexpand\@rvecadd*#1,\relax#2,\relax}\tmp}
\def\rvecdiv#1#2{\edef\tmp{\noexpand\@rvecadd/#1,\relax#2,\relax}\tmp}
\def\rcar#1{\edef\tmp{\noexpand\@rcar#1,\relax}\tmp}
\def\rcdr#1{\edef\tmp{\noexpand\@rcdr#1,\relax}\tmp}
%recursive macros
\def\@rvecadd#1#2,#3\relax#4,#5\relax{%
\the\numexpr#2#1#4\relax
\ifx\@#3\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi{,\@rvecadd#1#3\relax#5\relax} }
\def\@rcar#1,#2\relax{%
#1\relax
\ifx\@#2\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi}
\def\@rcdr#1,#2\relax{%
#2\relax
\ifx\@#2\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi}
\begin{document}
%Data
\def\a{5,3,0,100,1}
\def\b{5,1,6,1000,1}
\def\A{1,0,1\\0,2,0\\0,0,3}
\def\aT{5\\3\\0}
%Test
$(\a) + (\b) = (\rvecadd\a\b)$\par
$(\a) - (\b) = (\rvecsub\a\b)$\par
$(\a) * (\b) = (\rvecmul\a\b)$\par
$(\a) / (\b) = (\rvecdiv\a\b)$
%car test:
\rcar\a
%cdr test
(\rcdr\a)
\end{document}
答案1
现在没有时间做乘法了,但是可以做简单的向量加法/减法。
\documentclass{article}
\def\a{5,3,0}
\def\b{5,1,6}
\def\A{1,0,1\\0,2,0\\0,0,3}
%2) Vector addition: $\a+\b$ returns (10,4,6)
%3) Vector subtraction: $\a-\b$ returns (0,2,-6)
%4) Vector matrix multiplication: $\A*\aT$ returns (5,6,0)
\makeatletter
\def\rvecadd#1#2{\edef\tmp{\noexpand\@rvecadd+#1,\relax#2,\relax}\tmp}
\def\rvecsub#1#2{\edef\tmp{\noexpand\@rvecadd-#1,\relax#2,\relax}\tmp}
\def\@rvecadd#1#2,#3\relax#4,#5\relax{%
\the\numexpr#2#1#4\relax
\ifx\@#3\@\expandafter\@gobble
\else\expandafter\@firstofone
\fi{,\@rvecadd#1#3\relax#5\relax}}
\begin{document}
\def\a{5,3,0}
\def\b{5,1,6}
\def\A{1,0,1\\0,2,0\\0,0,3}
\def\aT{5\\3\\0}
$(\a) + (\b) = (\rvecadd\a\b)$
$(\a) - (\b) = (\rvecsub\a\b)$
\end{document}
答案2
我稍微改变了语法,省略了向量和矩阵中的括号。使用下面的代码,你可以做到
\setvector\a{5,3,0}
\setmatrix\A{1,0,1\\0,2,0\\0,0,3}
\begin{equation}
\usematrix\A \cdot \usevvector\a
= \matrixtimesvector\result\A\a \usevvector\result
\end{equation}
要显示矩阵(垂直),请计算\A
乘以乘以,并显示为垂直向量。\a
\result
\A
\a
\result
\documentclass{article}
\usepackage{expl3, xparse}
\usepackage{amsmath}
\ExplSyntaxOn
\seq_new:N \l__mypkg_a_seq
\seq_new:N \l__mypkg_b_seq
\seq_new:N \l__mypkg_result_seq
\int_new:N \l__mypkg_entries_int
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Declaring vectors and matrices
%
\cs_new_protected:Npn \mypkg_set_vector:Nnn #1#2#3
{
\seq_set_split:Nnn #1 {#2} {#3} % Split into entries.
\seq_set_map:NNn #1#1 { \fp_to_tl:n {##1} } % Evaluate each entry.
}
\NewDocumentCommand { \setvector } { m O{,} m }
{
\mypkg_set_vector:Nnn \l__mypkg_result_seq {#2} {#3}
\cs_set_eq:NN #1 \l__mypkg_result_seq
}
\NewDocumentCommand { \setmatrix } { m O{\\} O{,} m }
{
\seq_clear:N \l__mypkg_result_seq
\int_set_eq:NN \l__mypkg_entries_int \c_minus_one
\seq_set_split:Nnn \l__mypkg_a_seq {#2} {#4} % Split into lines.
\seq_map_inline:Nn \l__mypkg_a_seq
{
% Split each line |##1| into entries. For the first line,
% |\l__mypkg_entries_int| is -1 still; we set it to the
% number of entries in the first line. Then check that the line
% has the right number of entries: if so, put it in the result
% as a comma-delimited list, otherwise complain loudly and
% ignore the line.
%
\mypkg_set_vector:Nnn \l__mypkg_b_seq {#3} {##1}
\int_compare:nT { \l__mypkg_entries_int = \c_minus_one }
{
\int_set:Nn \l__mypkg_entries_int
{ \seq_count:N \l__mypkg_b_seq }
}
\int_compare:nTF
{ \seq_count:N \l__mypkg_b_seq = \l__mypkg_entries_int }
{
\seq_put_right:Nx \l__mypkg_result_seq
{ \seq_use:Nnnn \l__mypkg_b_seq { & } { & } { & } }
}
{
\msg_error:nnxxx { mypkg } { mismatched-lines }
{ \token_to_str:N #1 }
{ \int_use:N \l__mypkg_entries_int }
{ \seq_count:N \l__mypkg_b_seq }
}
}
\cs_set_eq:NN #1 \l__mypkg_result_seq
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Adding two vectors
%
\tl_new:N \l__mypkg_operation_tl
\NewDocumentCommand { \addvectors } { m m m }
{
\tl_set:Nn \l__mypkg_operation_tl { + }
\mypkg_add_vectors:NN #2#3
\cs_set_eq:NN #1 \l__mypkg_result_seq
}
\NewDocumentCommand { \subvectors } { m m m }
{
\tl_set:Nn \l__mypkg_operation_tl { - }
\mypkg_add_vectors:NN #2#3
\cs_set_eq:NN #1 \l__mypkg_result_seq
}
\cs_new_protected:Npn \mypkg_add_vectors:NN #1#2
{
\int_compare:nNnTF { \seq_count:N #1 } = { \seq_count:N #2 }
{
\seq_clear:N \l__mypkg_result_seq
\seq_mapthread_function:NNN #1#2 \mypkg_add_vectors:nn
}
{
\msg_error:nnxxxx { mypkg } { mismatched-vectors }
{ \token_to_str:N #1 } { \seq_count:N #1 }
{ \token_to_str:N #2 } { \seq_count:N #2 }
}
}
\cs_new_protected:Npn \mypkg_add_vectors:nn #1#2
{
\seq_put_right:Nx \l__mypkg_result_seq
{ \fp_to_tl:n { #1 \l__mypkg_operation_tl #2 } }
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Scalar product of two vectors
%
\NewDocumentCommand { \scalarproduct } { mmm }
{
\tl_set:Nx #1 { \mypkg_scalar_product:NN #2 #3 }
}
\cs_new:Npn \mypkg_scalar_product:NN #1#2
{
\fp_to_tl:n
{ \seq_mapthread_function:NNN #1 #2 \mypkg_scalar_product_aux:nn }
}
\cs_new:Npn \mypkg_scalar_product_aux:nn #1#2 { + #1 * #2 }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Multiplying matrix times vector
%
\NewDocumentCommand { \matrixtimesvector } { mmm }
{
\seq_clear:N \l__mypkg_result_seq
\seq_map_inline:Nn #2
{
\seq_set_split:Nnn \l__mypkg_a_seq { & } {##1}
\seq_put_right:Nx \l__mypkg_result_seq
{ \mypkg_scalar_product:NN \l__mypkg_a_seq #3 }
}
\cs_set_eq:NN #1 \l__mypkg_result_seq
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Displaying vectors and matrices
%
\NewDocumentCommand { \usehvector } { m }
{
\mode_if_math:F { \msg_warning:nn { mypkg } { text-mode } }
\ensuremath
{
\begin{pmatrix}
\seq_use:Nnnn #1 { , } { , } { , }
\end{pmatrix}
}
}
\NewDocumentCommand { \usevvector } { m }
{
\mode_if_math:F { \msg_warning:nn { mypkg } { text-mode } }
\ensuremath
{
\begin{pmatrix}
\seq_use:Nnnn #1 { \\ } { \\ } { \\ }
\end{pmatrix}
}
}
\NewDocumentCommand { \usematrix } { m }
{
\mode_if_math:F { \msg_warning:nn { mypkg } { text-mode } }
\ensuremath
{
\begin{pmatrix}
\seq_use:Nnnn #1 { \\ } { \\ } { \\ }
\end{pmatrix}
}
}
\msg_new:nnn { mypkg } { mismatched-lines }
{ The~lines~of~#1~should~have~#2~entries,~but~this~one~has~#3. }
\msg_new:nnn { mypkg } { mismatched-vectors }
{ The~vector~#1~has~#2~entries,~but~the~vector~#3~has~#4~entries. }
\msg_new:nnn { mypkg } { text-mode }
{ The~\iow_char:N\\use...~commands~should~only~be~used~in~math~mode. }
\ExplSyntaxOff
\begin{document}
\setvector\a{5,3,0}
\setvector\b{5,1,6}
\setmatrix\A{1,0,1\\0,2,0\\0,0,3}
Vector addition: $\usehvector\a+\usehvector\b$ returns
$\addvectors\result\a\b \usehvector\result$. Subtraction:
\begin{equation}
\usevvector\a - \usevvector\b
= \subvectors\result\a\b \usevvector\result .
\end{equation}
Scalar product:
\begin{equation}
\usehvector\a \cdot \usevvector\b
= \scalarproduct\result\a\b \result
\end{equation}
Matrix-vector product
\begin{equation}
\usematrix\A \cdot \usevvector\a
= \matrixtimesvector\result\A\a \usevvector\result
\end{equation}
% 2) Vector addition: $\a+\b$ returns (10,4,6)
% 3) Vector subtraction: $\a-\b$ returns (0,2,-6)
% 4) Vector matrix multiplication: $\A*\a$ returns (5,6,0)
\end{document}