bitte schauen Sie sich das folgende MWE an:
\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}
(Ignorieren Sie das Sterntyp-Argument, ich habe es zum Erstellen eines flachen Frac verwendet (ist jetzt nicht mehr nötig).)
Das funktioniert gut, wenn die Differenzierung auf 3 Variablen beschränkt ist. Gibt es eine Möglichkeit, dieses Makro auf mehr Variablen auszuweiten? So wird es nicht funktionieren, da es bereits 8 Argumente gibt.
Ich kenne „SplitList“ und „ProcessList“, aber hier ist es komplizierter, weil ich für jede Variable die Anzahl der Differenzierungen hinzufügen muss.
Irgendwelche Ideen?
Antwort1
Ein listofitems
Ansatz, der Schlüsselwerte verwendet. Die Syntax lautet beispielsweise
\pdiff[y=3,x,z,p=2,d=3,q,r=2,s]{f(x,y,z,p,d,q,r,s)}
Hier ist das 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}
Während die tikz
\foreach
oben verwendete Schleife eine leicht verständliche Konstruktion zum Durchlaufen eines Index ist, kann man die Verwendung des tikz
Pakets ganz vermeiden, indem man die im Paket integrierte Schleifenkonstruktion verwendet listofitems
. In diesem Fall verläuft die Schleife jedoch durch die Elemente der Liste, und man kann indirekt über auf die Indexnummer zugreifen \<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}
Antwort2
Es ist nicht nötig, das Rad neu zu erfinden: Es gibt bereits ein spezielles Paket: esdiff
, das Bewertungspunkte auch als Indizes verwaltet:
\documentclass{article}
\usepackage{esdiff}
\begin{document}
\[ \diffp{f(x, y, z)}{{x^{3333}}{y^{9999}}{z^{8888}}{t^{55555}}} \]%
\[ \diffp*{f(x, y, z)}{{x^{3333}}{y^{9999}}{z^{8888}}{t^{55555}}}{(x_0,y_0,z_0,t_0)} \]%
\end{document}
Antwort3
Sie können eine durch Kommas getrennte Liste für die Liste der Variablen verwenden. Ich verwende die Konvention, dass
x/2,y/3,z
steht für „zweimalX, drei Maljund einmalzx/2,y/3,z/1
". Wenn Sie möchten, können Sie auch verwenden .
\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}
Antwort4
AktualisierenEine bessere Version finden Sie am Ende.
Obwohl es Pakete gibt, um dies zu erreichen, stelle ich einen anderen Weg vor, da xparse
hier bereits die Verantwortung liegt ;-)
Eine Möglichkeit zum expl3
Aufteilen einer Liste von Ableitungsspezifizierern und Erstellen einer Tokenliste:
Syntax: \pdiff{x/3,y/4,z/17}{f(x,y,z)}
würde die dritte Ableitung in Bezug auf x, die vierte in Bezug auf y und die 17. in Bezug auf z angeben.
Das Weglassen der Vollmacht oder des Testaments /
wird als abgeleiteter Befehl interpretiert 1
.
(Eine Prüfung auf versehentliche negative Zahlen sollte hinzugefügt werden)
Das Funktionsargument wird nicht ausgewertet oder überprüft.
Die Anzahl der Ableitungen wird intern berechnet.
\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}
Verbesserte Version mit Prüfungen und automatischer Erweiterung der Variablen:
\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}