在一个早期帖子我问了一个关于编写灵活的导数宏的问题,有人建议 LaTeX3 版本可能更容易理解,所以我决定尝试编写一个。不幸的是,我遇到了一些问题。首先,我在开始实现对数值导数阶数求和的功能时遇到了麻烦。特别是,当我尝试将命令添加\@tempcnta\z@
到宏的清理部分时,我遇到了错误。由于我对 LaTeX 的了解极其有限,我不知道另一种方法来对数值导数阶数求和。我还尝试将命令包装在\ExplSyntaxOff
and中\ExplSyntaxOn
,但这没有帮助。其次,该命令有时需要比我想要的更多的括号。我认为下面注释的示例是一种合理的用法。但是,实现不支持这一点,并且需要一组额外的括号(如注释示例正下方所示)。我认为基本功能已经存在(我将主要使用第一个示例中所示的命令),但如果能获得额外的功能(对数值导数阶数求和并消除对额外括号的需求),那就太好了。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% allocate variables to typeset the derivative
\tl_new:N \l_myderivative_num_exp_tl
\tl_new:N \l_myderivative_den_tl
\tl_new:N \l_myderivative_den_factor_var_flag_tl
\tl_new:N \l_myderivative_den_factor_exp_tl
% function to write the derivative
\NewDocumentCommand{\derivative}{m>{\SplitList,}m}
{
% clear any old values
\tl_clear:N \l_myderivative_num_exp_tl
\tl_clear:N \l_myderivative_num_exp_flag_tl
\tl_clear:N \l_myderivative_den_tl
\tl_clear:N \l_myderivative_den_factor_var_flag_tl
\tl_clear:N \l_myderivative_den_factor_exp_flag_tl
% format the denominator
\tl_map_inline:nn { #2 }
{
\myderivative_add_den_factor:n { ##1 }
}
% write the derivative
\frac
{
\partial
\tl_if_empty:NF \l_myderivative_num_exp_flag_tl
{
^{\l_myderivative_num_exp_tl}
}
#1
}
{
\l_myderivative_den_tl
}
}
% helper function to process a factor in the denominator
\cs_new_protected:Npn \myderivative_add_den_factor:n #1
{
% clear the variables
\tl_clear:N \l_myderivative_den_factor_var_flag_tl
\tl_clear:N \l_myderivative_den_factor_exp_tl
\tl_if_empty:NF \l_myderivative_den_tl
{
% add a thin space if we've already processed at least one factor
\tl_put_right:Nn \l_myderivative_den_tl { \, }
}
% format the factor
\tl_map_inline:nn { #1 }
{
\myderivative_fmt_den_factor:n { ##1 }
}
% check for an implicit exponent
\tl_if_empty:NT \l_myderivative_den_factor_exp_flag_tl
{
\tl_if_empty:NF \l_myderivative_num_exp_tl
{
\tl_put_right:Nn \l_myderivative_num_exp_flag_tl { 1 }
\tl_put_right:Nn \l_myderivative_num_exp_tl { + }
}
\tl_put_right:Nn \l_myderivative_num_exp_tl { 1 }
}
}
% helper function to format a factor in the denominator
\cs_new_protected:Npn \myderivative_fmt_den_factor:n #1
{
\tl_if_empty:NTF \l_myderivative_den_factor_var_flag_tl
{
% if the flag is not set, then we are processing the variable
\tl_put_right:Nn \l_myderivative_den_tl { \partial #1 }
% set the flag
\tl_put_right:Nn \l_myderivative_den_factor_var_flag_tl { 1 }
}
{
% if the flag is set, then we are processing the exponent
\tl_put_right:Nn \l_myderivative_den_tl { ^{#1} }
% update the numerator exponent
\tl_if_empty:NF \l_myderivative_num_exp_tl
{
\tl_put_right:Nn \l_myderivative_num_exp_tl { + }
}
\tl_put_right:Nn \l_myderivative_num_exp_tl { #1 }
% set the flag
\tl_put_right:Nn \l_myderivative_den_factor_exp_flag_tl { 1 }
\tl_put_right:Nn \l_myderivative_num_exp_flag_tl { 1 }
}
}
\ExplSyntaxOff
\begin{document}
\[
\derivative{f}{xp,yq,zr}
\]
\[
\derivative{f}{x2,y3,z4}
\]
\[
\derivative{f}{x}
\]
\[
\derivative{f}{{\hat{x}}{2},{\tilde{y}}{3}}
\]
%\[
% \derivative{f}{{\hat{x}}}
%\]
\[
\derivative{f}{{{\hat{x}}}}
\]
\end{document}
答案1
实现可能看起来像
\documentclass{article}
\usepackage{expl3,xparse}
\makeatletter
\newcommand{\ifintegerTF}[1]{%
\ifnum`#1<`0 %
\expandafter\@secondoftwo
\else
\ifnum`#1>`9 %
\expandafter\expandafter\expandafter\@secondoftwo
\else
\expandafter\expandafter\expandafter\@firstoftwo
\fi
\fi
}
\ExplSyntaxOn
\int_new:N \l__stirling_total_int
\seq_new:N \l__stirling_denom_seq
\tl_new:N \l__stirling_denom_tl
\tl_new:N \l__stirling_numer_tl
\seq_new:N \l__stirling_powers_seq
\cs_new_protected:Npn \stirling_derivative:nn #1#2
{
\group_begin:
\int_zero:N \l__stirling_total_int
\seq_clear:N \l__stirling_powers_seq
\tl_clear:N \l__stirling_denom_tl
\clist_map_function:nN {#2} \__stirling_derivative_entry:n
\int_compare:nNnF \l__stirling_total_int = \c_zero
{
\seq_put_right:Nx \l__stirling_powers_seq
{ \int_use:N \l__stirling_total_int }
}
\tl_set:Nx \l__stirling_numer_tl
{
d
\seq_if_empty:NF \l__stirling_powers_seq
{
^
{ \seq_use:Nn \l__stirling_powers_seq { + } }
}
#1
}
\frac { \l__stirling_numer_tl } { \l__stirling_denom_tl }
\group_end:
}
\cs_new_protected:Npn \__stirling_derivative_entry:n #1
{
\__stirling_derivative_entry_aux:nw #1 \q_stop
}
\cs_new_protected:Npn \__stirling_derivative_entry_aux:nw #1#2 \q_stop
{
\tl_if_empty:NF \l__stirling_denom_tl
{ \tl_put_right:Nn \l__stirling_denom_tl { \, } }
\tl_if_empty:nTF {#2}
{
\int_incr:N \l__stirling_total_int
\tl_put_right:Nn \l__stirling_denom_tl { d #1 }
}
{
\seq_clear:N \l__stirling_denom_power_seq
\clist_map_function:nN {#2} \__stirling_derivative_entry_power:n
\tl_put_right:Nx \l__stirling_denom_tl
{
d #1 \exp_not:N ^
{
\seq_use:Nn \l__stirling_denom_power_seq { + }
}
}
}
}
\cs_new_protected:Npn \__stirling_derivative_entry_power:n #1
{
\ifintegerTF {#1}
{ \int_add:Nn \l__stirling_total_int {#1} }
{ \seq_put_right:Nn \l__stirling_powers_seq {#1} }
\seq_put_right:Nn \l__stirling_denom_power_seq {#1}
}
\DeclareDocumentCommand \derivative { m m }
{ \stirling_derivative:nn {#1} {#2} }
\ExplSyntaxOff
\begin{document}
\[
\derivative{x}{{y}{2},{z}{3}}
\]
\[
\derivative{x}{{y}{m},{z}{n}}
\]
\[
\derivative{x}{{v}{3},{w}{k,2},y,{z}{m}}
\]
\end{document}
我保留了\ifintegerTF
与旧问题中使用的命令相同的命令,并修复了另一个问题中提出的数学部分。除此之外,它非常简单明了。