次の MWE をご覧ください。
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\pdiff{s o m O{1} g O{1} g O{1}}% Star, function, variable 1, how many differentiations, ...
{\newcount\pdiffn% Count the number of differentiations
\advance\pdiffn #4\relax%
\IfValueT{#5}{\advance\pdiffn #6\relax}%
\IfValueT{#7}{\advance\pdiffn #8\relax}%
\frac%
{\partial \ifnum\pdiffn >1\relax ^{\the\pdiffn} \fi%
\IfValueT{#2}{#2}}%
{\IfValueT{#7}{\mathinner{\partial #7 \ifnum#8 >1\relax ^{#8} \fi}}%
\IfValueT{#5}{\mathinner{\partial #5 \ifnum#6 >1\relax ^{#6} \fi}}%
\mathinner{\partial #3 \ifnum#4 >1\relax ^{#4} \fi}}}
\begin{document}
\Huge
\[ \pdiff[f(x,y,z)]{y} \]
\[ \pdiff[f(x,y,z)]{y}[3]{x}{z} \]
\[ \pdiff[f(x,y,z)]{y}[9999]{x}[3333]{z}[8888] \]
\end{document}
(スター タイプの引数は無視してください。フラット フラックを作成するために使用しました (現在は必要ありません)。)
微分が 3 つの変数に制限されている場合、これはうまく機能します。このマクロをさらに多くの変数に拡張する可能性はありますか? この方法では、すでに 8 つの引数があるため機能しません。
「SplitList」と「ProcessList」はわかっていますが、ここでは変数ごとに微分の数を追加する必要があるため、より複雑です。
何か案は?
答え1
キー値を使用するアプローチlistofitems
。構文は、例えば
\pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)}
MWEはこちら
\documentclass{article}
\usepackage{listofitems,tikz}
\newcounter{totalindex}
\newcommand\pdiff[2][1]{%
\setsepchar{,/=}%
\readlist\Partialvars{#1}%
\setcounter{totalindex}{0}%
\foreach \Varindex in {1,...,\listlen\Partialvars[]}%
{%
\ifnum\listlen\Partialvars[\Varindex]>1\relax%
\addtocounter{totalindex}{\Partialvars[\Varindex,2]}%
\else%
\stepcounter{totalindex}%
\fi%
}%
\frac{\partial\ifnum\thetotalindex>1\relax^{\thetotalindex}\fi#2}%
{%
\foreach\Varindex in {1,...,\listlen\Partialvars[]}%
{%
\partial\Partialvars[\Varindex,1]%
\ifnum\listlen\Partialvars[\Varindex]>1\relax^{\Partialvars[\Varindex,2]}\fi%
}%
}%
}
\begin{document}
\[ \pdiff[y]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z]{f(x,y,z)} \]
\[ \pdiff[y=9999, x=3333, z=8888]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)} \]
\end{document}
上で使用したループtikz
\foreach
は、インデックスをループするためのわかりやすい構造ですが、パッケージtikz
に組み込まれているループ構造を使用して、パッケージの使用を完全に排除することもできますlistofitems
。ただし、この場合は、ループはリストの項目をループし、 を介して間接的にインデックス番号にアクセスできます\<loop-variable>cnt
。
\documentclass{article}
\usepackage{listofitems}
\newcounter{totalindex}
\newcommand\pdiff[2][1]{%
\setsepchar{,/=}%
\readlist\Partialvars{#1}%
\setcounter{totalindex}{0}%
\foreachitem \Var \in \Partialvars[]%
{%
\ifnum\listlen\Partialvars[\Varcnt]>1\relax%
\addtocounter{totalindex}{\Partialvars[\Varcnt,2]}%
\else%
\stepcounter{totalindex}%
\fi%
}%
\frac{\partial\ifnum\thetotalindex>1\relax^{\thetotalindex}\fi#2}%
{%
\foreachitem \Var \in \Partialvars%
{%
\partial\Partialvars[\Varcnt,1]%
\ifnum\listlen\Partialvars[\Varcnt]>1\relax^{\Partialvars[\Varcnt,2]}\fi%
}%
}%
}
\begin{document}
\[ \pdiff[y]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z]{f(x,y,z)} \]
\[ \pdiff[y=9999, x=3333, z=8888]{f(x,y,z)} \]
\[ \pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)} \]
\end{document}
答え2
答え3
変数のリストにはコンマ区切りのリストを使用できます。私は次のような規則を使用します。
x/2,y/3,z
「2回」を意味するバツ、3回ええそして一度ず」。x/2,y/3,z/1
必要に応じて を使用することもできます。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\pdiff}{smm}
{
\IfBooleanTF{#1}
{% with \pdiff* call the inner function for inline
\egreg_pdiff_inline:nn { #2 } { #3 } % TO DO
}
{% with \pdiff call the inner function for display
\egreg_pdiff_frac:nn { #2 } { #3 }
}
}
% allocate some variables
\int_new:N \l__egreg_pdiff_total_int
\seq_new:N \l__egreg_pdiff_vars_seq
\seq_new:N \l__egreg_pdiff_var_seq
\tl_new:N \l__egreg_pdiff_denom_tl
\cs_new_protected:Nn \egreg_pdiff_frac:nn
{
% clear the variables to be given values later
\int_zero:N \l__egreg_pdiff_total_int
\tl_clear:N \l__egreg_pdiff_denom_tl
% split the second argumen at commas
\seq_set_split:Nnn \l__egreg_pdiff_vars_seq { , } { #2 }
% map this sequence for adding to the denominator and
% computing the number of derivatives
\seq_map_function:NN \l__egreg_pdiff_vars_seq \__egreg_pdiff_var:n
% now print:
% \l__egreg_pdiff_total_int is set to the number of derivatives
% \l__egreg_pdiff_denom_tl contains the denominator
\frac
{
\partial
\int_compare:nT { \l__egreg_pdiff_total_int > 1 }
{ \sp { \int_to_arabic:n { \l__egreg_pdiff_total_int } } }
#1
}
{
\tl_use:N \l__egreg_pdiff_denom_tl
}
}
\cs_new_protected:Nn \__egreg_pdiff_var:n
{
% split the argument at / (it should be in the form 'x' or 'x/2')
\seq_set_split:Nnn \l__egreg_pdiff_var_seq { / } { #1 }
% if the sequence has one term, no exponent is present
\int_compare:nTF { \seq_count:N \l__egreg_pdiff_var_seq < 2 }
{% simple variable: add to the denominator and increment the number
\tl_put_right:Nn \l__egreg_pdiff_denom_tl { \partial #1 }
\int_incr:N \l__egreg_pdiff_total_int
}
{% multiple: add to the denominator and increment the number
% item 1 contains the variable, item 2 the exponent
\tl_put_right:Nx \l__egreg_pdiff_denom_tl
{
\partial
\seq_item:Nn \l__egreg_pdiff_var_seq { 1 }
\sp { \seq_item:Nn \l__egreg_pdiff_var_seq { 2 } }
}
\int_add:Nn \l__egreg_pdiff_total_int { \seq_item:Nn \l__egreg_pdiff_var_seq { 2 } }
}
}
\ExplSyntaxOff
\begin{document}
\[
\pdiff{f(x,y)}{x}
\quad
\pdiff{f(x,y,z)}{x/20,y/32,z}
\]
\end{document}
答え4
アップデート最後により良いバージョンをご覧ください。
これを実現するパッケージはありますが、xparse
ここではすでに担当しているので、別の方法を紹介します ;-)
expl3
派生指定子のリストを分割し、トークン リストを構築する方法:
構文: \pdiff{x/3,y/4,z/17}{f(x,y,z)}
x に関して 3 次微分、y に関して 4 次微分、z に関して 17 次微分を指定します。
累乗またはを省略すると、/
微分順序として解釈されます1
。
(偶発的な負の数のチェックを追加する必要があります)
関数の引数は評価もチェックもされません。
導関数の数は内部的に計算されます。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_generate_variant:Nn \int_add:Nn {Nx}
\seq_new:N \l_pdiff_deriv_seq
\NewDocumentCommand{\pdiffs}{mm}{%
\int_zero:N \l_tmpa_int
\seq_set_from_clist:Nn \l_tmpa_seq {#1} % Split the comma list
\seq_map_inline:Nn \l_tmpa_seq {% Traverse the local entries
\seq_set_split:Nnn \l_tmpb_seq {/} {##1}% Split into variable and order
\tl_put_right:Nn \l_tmpa_tl {\partial}% Built the nominator list
\int_compare:nNnTF {\seq_count:N \l_tmpb_seq } = {\c_one} {% Is there only one split element?
\seq_put_right:Nn \l_tmpb_seq {\c_one}% Yes
\tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}} % Add now 'power'
}{%
\int_compare:nNnTF {\seq_item:Nn \l_tmpb_seq {2}} = {\c_one } {
% Is the derivative order one --> no power?
\tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}}
}{
\tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}^{\seq_item:Nn \l_tmpb_seq {2}}}
}
}
\int_add:Nx \l_tmpa_int {\seq_item:Nn \l_tmpb_seq {2}}
}
% Display the list
\mathinner{\frac{\partial^{\int_use:N\l_tmpa_int}#2}{\tl_use:N \l_tmpa_tl}}
}
\ExplSyntaxOff
\begin{document}
\Huge
\[\pdiffs{x/5,y/3}{f(x,y,z)}\]
\[\pdiffs{x/4,y/8,z/17}{f(x,y,z)}\]
\end{document}
変数のチェックと自動拡張を備えた改良バージョン:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_generate_variant:Nn \int_add:Nn {Nx}
\cs_generate_variant:Nn \int_set:Nn {Nx}
\seq_new:N \l_pdiff_var_seq
\msg_new:nnn {pdiff}{negativedifforder}{Error:~The~order~of~derivative~is~negative~for~variable~#1!}
\NewDocumentCommand{\pdiffs}{mm}{%
\int_zero:N \l_tmpa_int
\tl_clear:N \l_tmpa_tl
\seq_clear:N \l_pdiff_var_seq
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_map_inline:Nn \l_tmpa_seq {%
\seq_set_split:Nnn \l_tmpb_seq {/} {##1}
\seq_put_right:Nx \l_pdiff_var_seq {\seq_item:Nn \l_tmpb_seq {1}}
\int_compare:nNnTF {\seq_count:N \l_tmpb_seq } = {\c_one} {
\int_set:Nn \l_tmpb_int {\c_one}
\seq_put_right:Nn \l_tmpb_seq {\c_one}
\tl_put_right:Nn \l_tmpa_tl {\partial}
\tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}}
}{%
\int_set:Nx \l_tmpb_int {\seq_item:Nn \l_tmpb_seq {2}}
\int_compare:nNnTF { \l_tmpb_int } < {\c_zero} {
\msg_fatal:nnx {pdiff}{negativedifforder}{\seq_item:Nn \l_tmpb_seq {1}}
}{%
\int_compare:nNnF {\l_tmpb_int } = {\c_zero} {%
\tl_put_right:Nn \l_tmpa_tl {\partial}
\int_compare:nNnTF{ \l_tmpb_int } = {\c_one } {
\tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}}
}{%
\tl_put_right:Nx \l_tmpa_tl {\seq_item:Nn \l_tmpb_seq {1}^{\seq_item:Nn \l_tmpb_seq {2}}}
}
}
}
}
\int_add:Nx \l_tmpa_int {\l_tmpb_int}
}
\mathinner{\frac{\partial^{\int_use:N\l_tmpa_int}#2(\seq_use:Nn \l_pdiff_var_seq {,})}{\tl_use:N \l_tmpa_tl}}
}
\ExplSyntaxOff
\begin{document}
\Huge
\[\pdiffs{x/5,y/3,z/0}{f}\]
\[\pdiffs{x/4,y/8,z/17}{f}\]
\end{document}