- Questo topic ha 10 risposte, 3 partecipanti ed è stato aggiornato l'ultima volta 14 anni, 8 mesi fa da
egreg9.
-
CreatoreTopic
-
18 Ottobre 2011 alle 8:14 #65009::
Salve, vorrei costruire una macro ricorsiva per continued fractions senza specificare il numero esatto di argomenti.`\documentclass{article}
\begin{document}\def\contfrac#1#2{\bb#1,\endbb,}
\def\bb#1#2,{\let\next\bb
\ifx#1\endbb\let\next\relax
\else
$#1+\cfrac{1}{#1+\cfrac{1}{#1+}}$\fi\next}\contfrac{1,2,3,4}
\end{document}`
Ho provato a scrivere la macro sopra per 4 numeri ma ottengo le varie parti della frazione come singole frazioni mentre io vorrei ottenere
`$1+\cfrac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}}$`
Potete indicarmi la sintassi esatta della macro? Spero in un aiuto dal forum.
Grazie.
-
CreatoreTopic
-
AutoreRisposte
-
-
18 Ottobre 2011 alle 11:57 #65010::
rudycol” post=64065Salve, vorrei costruire una macro ricorsiva per continued fractions senza specificare il numero esatto di argomenti.
`\documentclass{article}
\begin{document}\def\contfrac#1#2{\bb#1,\endbb,}
\def\bb#1#2,{\let\next\bb
\ifx#1\endbb\let\next\relax
\else
$#1+\cfrac{1}{#1+\cfrac{1}{#1+}}$\fi\next}\contfrac{1,2,3,4}
\end{document}`
Ho provato a scrivere la macro sopra per 4 numeri ma ottengo le varie parti della frazione come singole frazioni mentre io vorrei ottenere
$1+\cfrac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}}$
Potete indicarmi la sintassi esatta della macro? Spero in un aiuto dal forum.
Non facile; niente male come primo messaggio: benvenuto.
`\usepackage{etoolbox,amsmath}
\makeatletter
\newtoks\cf@toksa
\newtoks\cf@toksb
\newrobustcmd\contfrac[1]{\cf@toksa={}\cf@toksb={}%
\@for\next:=#1\do
{\cf@toksa=\expandafter{\the\expandafter\cf@toksa\expandafter\cf@start\expandafter{\next}}%
\cf@toksb=\expandafter{\the\cf@toksb\cf@end}}
\edef\cf@final{\the\cf@toksa\the\cf@toksb}%
\edef\cf@final{\cf@final}\expandafter\@gobblethree\cf@final}
\def\cf@start#1{+\noexpand\cfrac\iftrue{\else}\fi1\iffalse{\else}\fi\iftrue{\else}\fi#1}
\def\cf@end{\iffalse{\else}\fi}
\makeatletter`
Ora \contfrac{1,2,3,4} produce il risultato che puoi vedere qui sotto. Naturalmente richiede amsmath.Ciao
Enrico
-
18 Ottobre 2011 alle 14:50 #65011::
Ho provato la tua soluzione e funziona correttamente con un diverso numero di argomenti.Un ultimo dubbio:
Nel caso avessi delle continued fractions all’interno di una continued fraction il tuo comando mi crea un errore che dice che
! TeX capacity exceeded, sorry [input stack size=5000].
Mi riferisco ad un comando del tipo
\contfrac{1, 2, \contfrac{3, 4}}
in cui la macro è all’interno di un’altra macro. E’ possibile superare questo errore con una piccola modifica alla tua soluzione?
Grazie.
-
18 Ottobre 2011 alle 15:40 #65012::
rudycol” post=64082Ho provato la tua soluzione e funziona correttamente con un diverso numero di argomenti.
Un ultimo dubbio:
Nel caso avessi delle continued fractions all’interno di una continued fraction il tuo comando mi crea un errore che dice che
! TeX capacity exceeded, sorry [input stack size=5000].
Mi riferisco ad un comando del tipo
\contfrac{1, 2, \contfrac{3, 4}}
in cui la macro è all’interno di un’altra macro. E’ possibile superare questo errore con una piccola modifica alla tua soluzione?
Grazie.
Non mi pare che abbia molto senso. Comunque si può fare caricando il pacchetto etoolbox e modificando \def\contfrac#1 in \newrobustcmd\contfrac[1]. Modifico la definizione nel messaggio precedente.
Ciao
Enrico
-
18 Ottobre 2011 alle 18:45 #65013::
Una versione migliore, che però richiede un leggero cambiamento di sintassi:`\usepackage{etoolbox,amsmath}
\makeatletter
\toksdef\cf@toksa=0
\toksdef\cf@toksb=2
\newrobustcmd{\contfrac}[1]{\@contfracstart#1\@nil}
\def\@contfracstart#1;#2\@nil{%
\if\relax\detokenize{#1}\relax
\@contfrac{\noexpand\@gobble,#2}%
\else
\@contfrac{#1,#2}%
\fi}
\def\@contfrac#1{\cf@toksa={}\cf@toksb={}%
\@for\next:=#1\do
{\cf@toksa=\expandafter{\the\expandafter\cf@toksa\expandafter\cf@start\expandafter{\next}}%
\cf@toksb=\expandafter{\the\cf@toksb\cf@end}}
\edef\cf@final{\the\cf@toksa\the\cf@toksb}%
\edef\cf@final{\cf@final}\expandafter\@gobblethree\cf@final}
\def\cf@start#1{+\noexpand\cfrac{1}\iftrue{\else}\fi\unexpanded{#1}}
\def\cf@end{\iffalse{\else}\fi}
\makeatletter`Il cambiamento è il seguente: la parte intera della frazione continua va separata dal resto con un punto e virgola, che è poi una notazione corrente per le frazioni continue. Vediamo un paio di esempi:
`\[\contfrac{1;2,3,4}\]
\[\contfrac{;2,3,4}\]`
-
18 Ottobre 2011 alle 20:52 #65014::
Non so come ringraziarla per la sua infinità disponibilità. Sono un “novizio” di programmazione in LaTeX sebbene uso LaTeX da un pò e mi piacerebbe molto imparare.
Per vedere se ho capito esattamente come ha implementato la procedura, ho fatto dei commenti ai diversi steps preceduti dal simbolo %. Sarei molto grato se potrebbe controllare i vari commenti. Mille grazie.\@for\next:=#1\do{
% Per assegnare l’argomento del comando \contfrac e iniziare il loop\cf@toksa=\expandafter{
% Espande l’argomento e lo assegna al token A\the\expandafter\cf@toksa
% Questo dovrebbe assegnare il numero a sinistra di ogni frazione?\expandafter\cf@start
% Questa dovrebbe essere la frazione a destra di ogni numero nell’argomento di \contfrac\expandafter{\next}
%Ripete la procedura\cf@toksb=\expandafter{\the\cf@toksb\cf@end}
% Assegna al token B il suo corrente valore e conclude\edef\cf@final{\the\cf@toksa\the\cf@toksb}
% NON HO CAPITO COSA FA QUESTO COMANDO\edef\cf@final{\cf@final}\expandafter\@gobblethree\cf@final
% NON HO CAPITO COSA FA QUESTO COMANDO\def\cf@start#1{+\noexpand\cfrac\iftrue{\else}\fi1\iffalse{\else}\fi\iftrue{\else}\fi#1}
% Questa è la definizione di continued fraction\def\cf@end{\iffalse{\else}\fi}
% Definisce \@end per la falsa condizione e ferma il loopAl di là della continued fraction, se mi posso permettere, vorrei chiedere dei suggerimenti su del materiale su cui studiare. Attualmente ho il TeXbook di Knuth ma questo è limitato a un solo capitolo per le macro.
Grazie ancora,
Rudy
-
18 Ottobre 2011 alle 21:57 #65015::
rudycol” post=64095Non so come ringraziarla per la sua infinità disponibilità. Sono un “novizio” di programmazione in LaTeX sebbene uso LaTeX da un pò e mi piacerebbe molto imparare.
Per vedere se ho capito esattamente come ha implementato la procedura, ho fatto dei commenti ai diversi steps preceduti dal simbolo %. Sarei molto grato se potrebbe controllare i vari commenti. Mille grazie.\@for\next:=#1\do{
% Per assegnare l’argomento del comando \contfrac e iniziare il loop\cf@toksa=\expandafter{
% Espande l’argomento e lo assegna al token A\the\expandafter\cf@toksa
% Questo dovrebbe assegnare il numero a sinistra di ogni frazione?\expandafter\cf@start
% Questa dovrebbe essere la frazione a destra di ogni numero nell’argomento di \contfrac\expandafter{\next}
%Ripete la procedura\cf@toksb=\expandafter{\the\cf@toksb\cf@end}
% Assegna al token B il suo corrente valore e conclude\edef\cf@final{\the\cf@toksa\the\cf@toksb}
% NON HO CAPITO COSA FA QUESTO COMANDO\edef\cf@final{\cf@final}\expandafter\@gobblethree\cf@final
% NON HO CAPITO COSA FA QUESTO COMANDO\def\cf@start#1{+\noexpand\cfrac\iftrue{\else}\fi1\iffalse{\else}\fi\iftrue{\else}\fi#1}
% Questa è la definizione di continued fraction\def\cf@end{\iffalse{\else}\fi}
% Definisce \@end per la falsa condizione e ferma il loopAl di là della continued fraction, se mi posso permettere, vorrei chiedere dei suggerimenti su del materiale su cui studiare. Attualmente ho il TeXbook di Knuth ma questo è limitato a un solo capitolo per le macro.
Grazie ancora,
Rudy
Normalmente qui ci si dà del tu.
Temo che la tua analisi sia piuttosto carente. Non preoccuparti: si tratta di macro di livello piuttosto elevato.
• \@for\next=#1\do{…}
Questo prende l’argomento ed esegue un ciclo su tutti gli elementi della lista (con la virgola come separatore). A ogni passo del ciclo viene eseguito il contenuto del gruppo tra graffe che segue \do, la macro \next ha come espansione l’elemento della lista.• \cf@toksa=\expandafter{…}
Questo è il modo di assegnare un valore al registro token \cf@toksa; \expandafter serve per eseguire un’espansione prima dell’assegnazione effettiva.Il resto è più difficile. Lettura consigliata, gli Appunti di programmazione in TeX e LaTeX di un noto autore. 🙂
Ciao
Enrico
-
19 Ottobre 2011 alle 5:02 #65016::
Vediamo di dare qualche spiegazione.`\toksdef\cf@toksa=0
\toksdef\cf@toksb=2`Assegno nomi simbolici a due registri token, solo per facilitare l’uso di \expandafter più avanti
`\newrobustcmd{\contfrac}[1]{\@contfracstart#1\@nil}`
Dichiaro \contfrac come robusto, che risolve il problema delle chiamate annidate. Il suo compito è di avviare il riconoscimento della parte intera.`\def\@contfracstart#1;#2\@nil{%
\if\relax\detokenize{#1}\relax
\@contfrac{\noexpand\@gobble,#2}%
\else
\@contfrac{#1,#2}%
\fi}`L’argomento è del tipo {1;2,3,4} oppure {;2,3,4} e \@confracstart riconosce se non c’è nulla prima del punto e virgola; nei due casi chiamerà \@contfrac{1,2,3,4} e \@contfrac{\noexpand\@gobble,2,3,4}
`\def\@contfrac#1{\cf@toksa={}\cf@toksb={}%
\@for\next:=#1\do
{\cf@toksa=\expandafter{\the\expandafter\cf@toksa\expandafter\cf@start\expandafter{\next}}%
\cf@toksb=\expandafter{\the\cf@toksb\cf@end}}
\edef\cf@final{\the\cf@toksa\the\cf@toksb}%
\edef\cf@final{\cf@final}\expandafter\@gobblethree\cf@final}`Inizializziamo i due registri token. Poi avviamo un ciclo sulla lista data come argomento; nel caso di \contfrac{1;2,3,4} \next assumerà i valori 1 2 3 4 nei quattro cicli eseguiti. La prima istruzione del ciclo è
`\cf@toksa=\expandafter{\the\expandafter\cf@toksa\expandafter\cf@start\expandafter{\next}}`
Con \expandafter faccio in modo che sia espanso \next prima che l’assegnazione abbia luogo; nel primo ciclo \cf@toksa conterrà “\cf@start{1}”, nel secondo “\cf@start{1}\cf@start{2}” e così via accumulando. Allo stesso tempo al registro \cf@toksb viene aggiunto un token \cf@end.Con \edef\cf@final{\the\cf@toksa\the\cf@toksb} otterremo, nei due casi, il seguente valore per \cf@final:
`\cf@start{1}\cf@start{2}\cf@start{3}\cf@start{4}\cf@end\cf@end\cf@end\cf@end
\cf@start{\noexpand\@gobble}\cf@start{2}\cf@start{3}\cf@start{4}\cf@end\cf@end\cf@end\cf@end`Rimandiamo a dopo i due ultimi passi e vediamo come sono definite \cf@start e \cf@end.
`\def\cf@start#1{+\noexpand\cfrac{1}\iftrue{\else}\fi\unexpanded{#1}}`
\cf@start ha un argomento e si espande a qualcosa che contiene condizionali; nel caso di \cf@start{1} avremo
`+\noexpand\cfrac{1}\iftrue{\else}\fi\unexpanded{1}`
che, quando sarà passato per una \edef diventerà
`+\cfrac{1}{1`
(\unexpanded serve perché il passaggio attraverso \edef non espanda #1, non ci serve e sarebbe sbagliato se #1 fosse qualcosa di più complicato di un numero)
`\def\cf@end{\iffalse{\else}\fi}`
L’espansione di \cf@end fornisce la graffa di chiusura, quando si passa nella \edef.Torniamo alle istruzioni che avevamo lasciato da parte:
`\edef\cf@final{\cf@final}`
Ridefinisco \cf@final come la sua espansione (per risparmiare su un nome); nel caso di \contfrac{1;2,3,4} avremo, come espansione finale di \cf@final
`+\cfrac{1}{1+\cfrac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}}}`
Rimane l’ultimo passaggio:
`\expandafter\@gobblethree\cf@final`
\@gobblethree (che mangia i tre argomenti che seguono) si trova davanti l’espansione di \cf@final e così rimane solo
`{1+\cfrac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}}}`
Nel caso di \contfrac{;2,3,4} alla fine si avrebbe
`{\@gobble+\cfrac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}}}`
che fa sparire il +
Ciao
Enrico
-
16 Gennaio 2012 alle 17:59 #65017::
A qualcuno potrebbe interessare la macro per le frazioni continue realizzata con LaTeX3; c’è qualche lieve modifica rispetto alla precedente, ma niente di fondamentale. Il comando \cfracdots può essere usato per indicare omissioni di termini. La cosa in più è la versione asterisco che produce la versione “in linea”.`\documentclass[a4paper]{article}
\usepackage{amsmath,xparse}\ExplSyntaxOn
\NewDocumentCommand{\cfracdots}{ }
{
\rule{0pt}{2.5\baselineskip}
\raisebox{\baselineskip}{\quad$\ddots$\quad}
}
\NewDocumentCommand{\xcontfrac}{ s >{\SplitArgument{1}{;}}m }
{
\IfBooleanTF{#1}
{ \cfrac_inline:nn #2 }
{ \cfrac_map:nn #2 }
}\cs_new:Npn \cfrac_inline:nn #1 #2
{
\IfNoValueTF { #2 }
{
\tl_use:N \c_cfrac_message_tl
\xcontfrac*{;#1}
}
{
\group_begin:
\cs_set_eq:NN \cfracdots \dots
[ \tl_if_empty:nTF { #1 } { 0 } { #1 } ; #2 ]
\group_end:
}
}\tl_const:Nn \c_cfrac_lbrace_tl { \if_true: { \else: } \fi: }
\tl_const:Nn \c_cfrac_rbrace_tl { \if_false: { \else: } \fi: }
\tl_const:Nn \c_cfrac_strut_tl { \vrule width 0pt depth .3\baselineskip }
\tl_const:Nn \c_cfrac_message_tl
{
\typeout{Wrong~syntax~for~\token_to_str:N \xcontfrac,~
assuming~0~in~the~integer~part,~on~line~\the\inputlineno.}
}
\tl_new:N \l_cfrac_left_tl
\tl_new:N \l_cfrac_right_tl\cs_new:Npn \cfrac_map:nn #1 #2
{
\tl_clear:N \l_cfrac_left_tl \tl_clear:N \l_cfrac_right_tl
\IfNoValueTF { #2 }
{
\tl_use:N \c_cfrac_message_tl
\xcontfrac{;#1}
}
{
\tl_if_empty:nTF { #1 }
{ \cfrac_map_aux:n { \exp_not:N \use_none:n , #2 } }
{ \cfrac_map_aux:n { #1 , #2 } }
}
}
\cs_new:Npn \cfrac_map_aux:n #1
{
\clist_map_inline:nn { #1 }
{
\tl_put_right:Nn \l_cfrac_left_tl { \cfrac_begin:n { ##1 } }
\tl_put_right:Nn \l_cfrac_right_tl { \exp_not:N \c_cfrac_rbrace_tl }
}
\tl_set:Nx \l_cfrac_left_tl
{ \l_cfrac_left_tl \c_cfrac_strut_tl \l_cfrac_right_tl }
\tl_set:Nx \l_cfrac_left_tl { \l_cfrac_left_tl }
\exp_after:wN \use_none:nnn \l_cfrac_left_tl
}
\cs_new:Npn \cfrac_begin:n #1
{
\exp_not:n
{ + \exp_not:N \cfrac { 1 } \c_cfrac_lbrace_tl #1 }
}
\ExplSyntaxOff\begin{document}
\begin{gather*}
\xcontfrac*{1;2,3,4}=\xcontfrac{1;2,3,4} \\
\xcontfrac*{;2,3,4}=\xcontfrac{;2,3,4} \\
\xcontfrac*{2,3,4}=\xcontfrac{2,3,4}
\end{gather*}
\end{document}`
Ciao
Enrico
-
16 Gennaio 2012 alle 22:40 #65018
-
16 Gennaio 2012 alle 23:31 #65019::
OldClaudio” post=67846Davvero bella, bravo Enrico.
È essenzialmente la stessa di prima; l’idea è di mostrare le potenzialità del sistema, che rende più semplici molti compiti che andavano reinventati ogni volta. Per esempio, invece del complicato \@for\next:=#1\do{…} per trattare con liste di elementi separati da virgole, c’è
`\clist_map_inline:nn {#1} {codice da eseguire in cui i successivi elementi della lista si indicano con ##1}`
Niente \next e, per di più, gli spazi attorno agli elementi sono eliminati automaticamente.Ciao
Enrico
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.