Eliminare pt dall’espansione di \the

  • Creatore
    Topic
  • #76064
    robitex
    Amministratore del forum
      Up
      0
      Down
      ::


      Ciao.
      Ho creato un registro dimensionale sul quale eseguo delle operazioni di somma e divisione.
      Alla fine ho quindi un valore numerico puro e mi occorre l’espansione dei token del numero per passarlo ad un comando di pgfplots, per ottenere un dimensionamento automatico di un ‘pannello’ all’interno dell’area di un grafico.
      L’espansione dovrà poi andare all’interno di un istruzione TikZ tipo \draw (axis cs:44, \y)…

      Il odice che ho scritto è il seguente:
      `\newdimen\ypanel
      \ypanel = 8cm
      \advance\ypanel by -38pt% margini sup+inf (in realtà i 38pt sono l'altezza di un box variabile)
      \divide\ypanel by 228 % 80mm/0.35pt circa

      % elimino i pt dall'espansione di \the\yanel con un comando
      % con argomenti delimitati
      \def\ptcut#1pt{#1}
      \def\yp{\expandafter\ptcut\expandafter{\the\ypanel}}`

      L’errore che ottengo è invece:
      Runaway argument?
      {0.81413pt}
      ! Paragraph ended before \ptcut was complete.

      \par
      So che sto facendo un errore banale, perdonatemi se vi chiedo aiuto…
      R.

    Visualizzazione 14 filoni di risposte
    • Autore
      Risposte
      • #76065
        Up
        0
        Down
        ::

        robitex” post=75242Ciao.
        Ho creato un registro dimensionale sul quale eseguo delle operazioni di somma e divisione.
        Alla fine ho quindi un valore numerico puro e mi occorre l’espansione dei token del numero per passarlo ad un comando di pgfplots, per ottenere un dimensionamento automatico di un ‘pannello’ all’interno dell’area di un grafico.
        L’espansione dovrà poi andare all’interno di un istruzione TikZ tipo \draw (axis cs:44, \y)…

        Il odice che ho scritto è il seguente:
        `\newdimen\ypanel
        \ypanel = 8cm
        \advance\ypanel by -38pt% margini sup+inf (in realtà i 38pt sono l'altezza di un box variabile)
        \divide\ypanel by 228 % 80mm/0.35pt circa

        % elimino i pt dall'espansione di \the\yanel con un comando
        % con argomenti delimitati
        \def\ptcut#1pt{#1}
        \def\yp{\expandafter\ptcut\expandafter{\the\ypanel}}`

        L’errore che ottengo è invece:
        Runaway argument?
        {0.81413pt}
        ! Paragraph ended before \ptcut was complete.

        \par
        So che sto facendo un errore banale, perdonatemi se vi chiedo aiuto…
        R.

        Il problema è che [tt]\the\ypanel[/tt] produce token di categoria 12, mentre nella tua definizione [tt]pt[/tt] sono di categoria 11:
        `\begingroup\lccode`!=`p \lccode`?=`t
        \lowercase{\endgroup\def\ptcut#1!?{#1}}`
        Funziona perché [tt]\lowercase[/tt] non cambia i codici di categoria.

        Metodo alternativo (un po’ di pubblicità non guasta :))
        `\usepackage{regexpatch}
        \def\ptcut#1pt{#1}
        \xpatchparametertext{\ptcut}{pt}{\cO p \cO t}{}{}`

        Metodo molto più semplice: usare `\strip@pt`: con
        `\strip@pt\ypanel`
        ottieni proprio il numero (richiede alcuni passi di espansione, quindi bisognerebbe sapere un po’ di più sull’uso che devi farne).

        Ciao
        Enrico

      • #76066
        robitex
        Amministratore del forum
          Up
          0
          Down
          ::


          Non era poi così banale…
          Grazie mille per le accurate spiegazioni.
          ps. \strip@pt\ fa parte del nucleo di LaTeX vero?
          R.

        • #76067
          Up
          0
          Down
          ::

          robitex” post=75246Non era poi così banale…
          Grazie mille per le accurate spiegazioni.
          ps. \strip@pt\ fa parte del nucleo di LaTeX vero?
          R.

          Sì, certo.

          Ciao
          Enrico

        • #76068
          OldClaudio
          Partecipante
            Up
            0
            Down
            ::

            robitex” post=75246Non era poi così banale…
            Grazie mille per le accurate spiegazioni.
            ps. \strip@pt\ fa parte del nucleo di LaTeX vero?
            R.

            Le magie di Enrico non sono per niente banali, ma sono pensate e prendono in considerazione anche questioni riguardanti l’eventuale numero di espansioni e di conseguenza la fragilità dei comandi.

            Tuttavia, come dice Enrico, usare \strip@pt, comando del nucleo di LaTeX da quando questo genere di conti deve essere eseguito per gestire i font con il New Font Selection Scheme (che a noi non sembra nemmeno più nuovo, visto che lo usiamo dal 1994, da quando è uscito il LaTeX2e). Ovviamante non è documentato, almeno non lo è se non si vanno a leggere i documenti ltx….dtx nella cartella source.
            Io ho scoperto \strop@pt un 7-8 anni fa e da allora per me è diventato un comando di uso quasi giornaliero. Non trovo che sia fragile, anche se forse lo è; dipende da come viene usato, naturalmente, ma non mi è mai capitato che il comando mi si “rompesse” fra le mani; tra l’altro la sua sintassi è semplicissima:

            [tt]\strip@pt[/tt]

            Nel tuo caso, per esempio:
            `\edef\yp{\strip@pt\ypanel}`
            permette di stivare in \yp solamente il valore in punti senza “pt”; esattamente quello che volevi fare e fatto in modo semplicissimo.
            Certo se la definizione di \strip@pt fosse fatta con la seconda definizione di Enrico ne guadagnerebbe anche il codice interno di LaTeX.

          • #76069
            Up
            0
            Down
            ::

            OldClaudio” post=75252

            Non era poi così banale…
            Grazie mille per le accurate spiegazioni.
            ps. \strip@pt\ fa parte del nucleo di LaTeX vero?
            R.

            Le magie di Enrico non sono per niente banali, ma sono pensate e prendono in considerazione anche questioni riguardanti l’eventuale numero di espansioni e di conseguenza la fragilità dei comandi.

            Tuttavia, come dice Enrico, usare \strip@pt, comando del nucleo di LaTeX da quando questo genere di conti deve essere eseguito per gestire i font con il New Font Selection Scheme (che a noi non sembra nemmeno più nuovo, visto che lo usiamo dal 1994, da quando è uscito il LaTeX2e). Ovviamante non è documentato, almeno non lo è se non si vanno a leggere i documenti ltx….dtx nella cartella source.
            Io ho scoperto \strop@pt un 7-8 anni fa e da allora per me è diventato un comando di uso quasi giornaliero. Non trovo che sia fragile, anche se forse lo è; dipende da come viene usato, naturalmente, ma non mi è mai capitato che il comando mi si “rompesse” fra le mani; tra l’altro la sua sintassi è semplicissima:

            [tt]\strip@pt[/tt]

            Nel tuo caso, per esempio:
            `\edef\yp{\strip@pt\ypanel}`
            permette di stivare in \yp solamente il valore in punti senza “pt”; esattamente quello che volevi fare e fatto in modo semplicissimo.
            Certo se la definizione di \strip@pt fosse fatta con la seconda definizione di Enrico ne guadagnerebbe anche il codice interno di LaTeX.

            [tt]\strip@pt[/tt] fa qualcosa di più: se il valore del registro è un numero intero di punti, elimina il [tt].0[/tt] che rimarrebbe dall’espansione di [tt]\the\ypanel[/tt]

            Ciao
            Enrico

          • #76070
            robitex
            Amministratore del forum
              Up
              0
              Down
              ::


              Discussione in fondo interessante.
              Dovrei riuscire a pulire il codice per pubblicarne l’applicazione.
              Grazie a tutti.
              R.

            • #76071
              OldClaudio
              Partecipante
                Up
                0
                Down
                ::

                \strip@pt fa qualcosa di più: se il valore del registro è un numero intero di punti, elimina il .0 che rimarrebbe dall’espansione di \the\ypanel

                È vero, ma qualche volta rimpiango che lo faccia; ci sono circostanze in cui preferirei che il [tt].0[/tt] restasse. E per rimettercelo dovo fare altre (piccole) acrobazie per esaminare il valore che \strip@pt mi ha lasciato e eventualmente appendere quella piccola stringa.

              • #76072
                robitex
                Amministratore del forum
                  Up
                  0
                  Down
                  ::


                  Ciao,
                  ad un certo punto della procedura occorre fare un rapporto tra due lunghezze.
                  Poiché sia \divide che \dimexpr dividono solo per numeri interi, alla fine sono passato alla libreria \pgfmath, visto che l’avevo tra l’altro già disponibile perché caricata dal pacchetto pgfplots, superando il problema.

                  Il codice completo è il seguente (la parte di codice che interessa la discussione è nel preambolo, e caso mai date un occhiata alla correttezza della costruzione della \vbox):
                  `
                  % make with 'Spectrum' Lua library
                  % !TEX encoding = UTF-8
                  % !TEX program = pdflatex

                  \documentclass{standalone}
                  \usepackage[T1]{fontenc}
                  \usepackage[utf8]{inputenc}
                  \usepackage[italian]{babel}

                  \usepackage{lmodern}
                  \usepackage{pgfplots}
                  \usepackage[output-decimal-marker={,},
                  arc-separator=\,]{siunitx}

                  \pgfplotsset{compat=1.5}

                  \newbox\panel
                  \setbox\panel=\hbox{\rule{2pt}{0pt}\scriptsize
                  \vbox{%
                  \hbox{Sito: Carrara (MS)}
                  \hbox{Latidudine ED50 $\varphi=\ang{44;05;4.04}$}
                  \hbox{Longitudine ED50 $\lambda=\ang{10;06;16.27}$}
                  \hbox{Categoria di suolo: A}
                  \hbox{Categoria topografica T3 ($S_\mathrm{T}=\num{1.10}$)}}}

                  \newdimen\hg
                  \hg=72mm

                  \def\ymax{0.60}

                  \newdimen\yp
                  \yp=0pt
                  \advance\yp by \ht\panel
                  \advance\yp by \dp\panel
                  \advance\yp by 5pt% margine sup.

                  \pgfmathparse{\ymax*(1-\yp/\hg)}
                  \let\ylegend\pgfmathresult

                  \advance\yp by 5.6mm% spazio per legenda
                  \pgfmathparse{\ymax*(1-\yp/\hg)}
                  \let\ybox\pgfmathresult

                  \begin{document}
                  \begin{tikzpicture}
                  \begin{axis}[scale only axis,
                  legend columns=4,
                  tick label style={font=\scriptsize},
                  xmin=0,
                  ylabel={$S_\mathrm{e}/g$},
                  ymin=0,
                  grid=major,
                  ymax=\ymax,
                  xmax=3.0,
                  xlabel={$T$ (s)},
                  width=115mm,
                  height=\hg,
                  variable=\T,
                  xtick={0.0,0.5,1.0,1.5,2.0,2.5,3.0},
                  legend style={draw=none, at={(axis cs:3.000, \ylegend)}}]

                  \addplot coordinates {
                  (0.000, 0.214)
                  (0.099, 0.510)
                  (0.298, 0.510)
                  };
                  \addplot {0.15177/T};

                  \addplot {0.36105/T^2};

                  \addplot coordinates {
                  (0.000, 0.167)
                  (0.096, 0.401)
                  (0.289, 0.401)
                  };
                  \addplot {0.11591/T};

                  \addplot {0.25584/T^2};

                  \addplot coordinates {
                  (0.000, 0.067)
                  (0.084, 0.167)
                  (0.251, 0.167)
                  };
                  \addplot {0.04188/T};

                  \addplot {0.07725/T^2};

                  \addplot coordinates {
                  (0.000, 0.054)
                  (0.080, 0.132)
                  (0.239, 0.132)
                  };
                  \addplot {0.03151/T};

                  \addplot {0.05656/T^2};

                  % legenda spettri:
                  \legend{\textsc{slc},,,
                  \textsc{slv},,,
                  \textsc{sld},,,
                  \textsc{slo},,,
                  }
                  % add text info
                  \draw[black,fill=white]
                  (axis cs:3.000,\ybox) rectangle (axis cs:1.500,0.600)
                  node[anchor=north west]
                  {\box\panel};

                  \end{axis}
                  \end{tikzpicture}
                  \end{document}`

                  Grazie.

                • #76073
                  OldClaudio
                  Partecipante
                    Up
                    0
                    Down
                    ::


                    Non è vero che \dimexpr divida solo per numeri interi, anzi esegue l’operazione a*b/c nell’ordine conservando il risultato parziale della moltiplicazione in un registro a 64 bit, per cui non ci sono pericoli di overflow, almeno nella moltiplicazione.

                    Ma se devi calcolare il rapporto di due lunghezze a e c, metti usi per b la lungezza \p@ (che è una lunghezza di 1pt, e assegni il risultato di \dimexr a una dimensione. Credo di avere gia provato a metter \dimexpr come argomento di \the e mi pare di ricordare di non avere avuto bisogno di disturbare un registro temporaneo; mi pare di ricordare di aver eseguito cose del tipo [tt]\strip@pt\dimexpr a*b/c\relax[/tt] senza nessun problema. Il vantoggio è che tutte le operazioni eseguite da \dimexpr sono eseguite nei registri della cpu e non richiedono conversioni da e per cs di LaTeX.

                    Ricorda solo che \dimexpr arrotonda il risultato all’intero più vicino, mentre \divide semplicemente tronca, ma non è necessario ricorrere a \divide. Io lo facevo anni fa, quando le estensioni di eTeX non erano ancora incorporate dentro pdftex e xetex. luatex non ne ha bisogno perché sa fare i calcoli con lua. Avevo implementato con i comandi tradizionali di TeX la “long division” estraendo una cifra alla volta del quoziente, calcolando il resto, moltiplicando per 10 e ricominciando. Funzionava benissimo, ma ovviamente richiedeva di lavorare con gli scaled points e gestire il separatore decimale a parte. Tikz e pgfplots, con la loro libreria matematica non esistevano ancora…:wink:

                  • #76074
                    Up
                    0
                    Down
                    ::

                    robitex” post=75299Ciao,
                    ad un certo punto della procedura occorre fare un rapporto tra due lunghezze.
                    Poiché sia \divide che \dimexpr dividono solo per numeri interi, alla fine sono passato alla libreria \pgfmath, visto che l’avevo tra l’altro già disponibile perché caricata dal pacchetto pgfplots, superando il problema.

                    Il codice completo è il seguente (la parte di codice che interessa la discussione è nel preambolo, e caso mai date un occhiata alla correttezza della costruzione della \vbox):
                    `
                    % make with 'Spectrum' Lua library
                    % !TEX encoding = UTF-8
                    % !TEX program = pdflatex

                    \documentclass{standalone}
                    \usepackage[T1]{fontenc}
                    \usepackage[utf8]{inputenc}
                    \usepackage[italian]{babel}

                    \usepackage{lmodern}
                    \usepackage{pgfplots}
                    \usepackage[output-decimal-marker={,},
                    arc-separator=\,]{siunitx}

                    \pgfplotsset{compat=1.5}

                    \newbox\panel
                    \setbox\panel=\hbox{\rule{2pt}{0pt}\scriptsize
                    \vbox{%
                    \hbox{Sito: Carrara (MS)}
                    \hbox{Latidudine ED50 $\varphi=\ang{44;05;4.04}$}
                    \hbox{Longitudine ED50 $\lambda=\ang{10;06;16.27}$}
                    \hbox{Categoria di suolo: A}
                    \hbox{Categoria topografica T3 ($S_\mathrm{T}=\num{1.10}$)}}}

                    \newdimen\hg
                    \hg=72mm

                    \def\ymax{0.60}

                    \newdimen\yp
                    \yp=0pt
                    \advance\yp by \ht\panel
                    \advance\yp by \dp\panel
                    \advance\yp by 5pt% margine sup.

                    \pgfmathparse{\ymax*(1-\yp/\hg)}
                    \let\ylegend\pgfmathresult

                    \advance\yp by 5.6mm% spazio per legenda
                    \pgfmathparse{\ymax*(1-\yp/\hg)}
                    \let\ybox\pgfmathresult

                    \begin{document}
                    \begin{tikzpicture}
                    \begin{axis}[scale only axis,
                    legend columns=4,
                    tick label style={font=\scriptsize},
                    xmin=0,
                    ylabel={$S_\mathrm{e}/g$},
                    ymin=0,
                    grid=major,
                    ymax=\ymax,
                    xmax=3.0,
                    xlabel={$T$ (s)},
                    width=115mm,
                    height=\hg,
                    variable=\T,
                    xtick={0.0,0.5,1.0,1.5,2.0,2.5,3.0},
                    legend style={draw=none, at={(axis cs:3.000, \ylegend)}}]

                    \addplot coordinates {
                    (0.000, 0.214)
                    (0.099, 0.510)
                    (0.298, 0.510)
                    };
                    \addplot {0.15177/T};

                    \addplot {0.36105/T^2};

                    \addplot coordinates {
                    (0.000, 0.167)
                    (0.096, 0.401)
                    (0.289, 0.401)
                    };
                    \addplot {0.11591/T};

                    \addplot {0.25584/T^2};

                    \addplot coordinates {
                    (0.000, 0.067)
                    (0.084, 0.167)
                    (0.251, 0.167)
                    };
                    \addplot {0.04188/T};

                    \addplot {0.07725/T^2};

                    \addplot coordinates {
                    (0.000, 0.054)
                    (0.080, 0.132)
                    (0.239, 0.132)
                    };
                    \addplot {0.03151/T};

                    \addplot {0.05656/T^2};

                    % legenda spettri:
                    \legend{\textsc{slc},,,
                    \textsc{slv},,,
                    \textsc{sld},,,
                    \textsc{slo},,,
                    }
                    % add text info
                    \draw[black,fill=white]
                    (axis cs:3.000,\ybox) rectangle (axis cs:1.500,0.600)
                    node[anchor=north west]
                    {\box\panel};

                    \end{axis}
                    \end{tikzpicture}
                    \end{document}`

                    Grazie.

                    Non trascurerei la libreria l3fp. A giorni dovrebbe uscire l’aggiornamento in cui tutte le operazioni saranno espandibili come quelle con \numexpr e \dimexpr (che non è il caso di pgfmath).

                    Ciao
                    Enrico

                  • #76075
                    robitex
                    Amministratore del forum
                      Up
                      0
                      Down
                      ::

                      egreg9″ post=75305
                      Non trascurerei la libreria l3fp. A giorni dovrebbe uscire l’aggiornamento in cui tutte le operazioni saranno espandibili come quelle con \numexpr e \dimexpr (che non è il caso di pgfmath).

                      Ciao
                      Enrico

                      Buono a sapersi!
                      Quelli di LaTeX3 la sanno lunga…
                      Ciao

                    • #76076
                      robitex
                      Amministratore del forum
                        Up
                        0
                        Down
                        ::

                        OldClaudio” post=75303Non è vero che \dimexpr divida solo per numeri interi, anzi esegue l’operazione a*b/c nell’ordine conservando il risultato parziale della moltiplicazione in un registro a 64 bit, per cui non ci sono pericoli di overflow, almeno nella moltiplicazione.

                        Ma se devi calcolare il rapporto di due lunghezze a e c, metti usi per b la lungezza \p@ (che è una lunghezza di 1pt, e assegni il risultato di \dimexr a una dimensione. Credo di avere gia provato a metter \dimexpr come argomento di \the e mi pare di ricordare di non avere avuto bisogno di disturbare un registro temporaneo; mi pare di ricordare di aver eseguito cose del tipo [tt]\strip@pt\dimexpr a*b/c\relax[/tt] senza nessun problema. Il vantoggio è che tutte le operazioni eseguite da \dimexpr sono eseguite nei registri della cpu e non richiedono conversioni da e per cs di LaTeX.

                        Ricorda solo che \dimexpr arrotonda il risultato all’intero più vicino, mentre \divide semplicemente tronca, ma non è necessario ricorrere a \divide. Io lo facevo anni fa, quando le estensioni di eTeX non erano ancora incorporate dentro pdftex e xetex. luatex non ne ha bisogno perché sa fare i calcoli con lua. Avevo implementato con i comandi tradizionali di TeX la “long division” estraendo una cifra alla volta del quoziente, calcolando il resto, moltiplicando per 10 e ricominciando. Funzionava benissimo, ma ovviamente richiedeva di lavorare con gli scaled points e gestire il separatore decimale a parte. Tikz e pgfplots, con la loro libreria matematica non esistevano ancora…:wink:

                        Ciao Claudio,
                        ho provato a dividere due dimensioni ma con strani risultati, per esempio:
                        `\documentclass{article}

                        \newdimen\numer
                        \newdimen\denom

                        \numer=150pt
                        \denom=150pt

                        \divide\numer by \denom

                        \begin{document}
                        \the\numer% -> 0.00002pt invece di 1pt
                        \end{document}`

                        Con \dimexpr ho fatto questo tentativo:
                        `\documentclass{article}

                        \newdimen\numer
                        \newdimen\denom

                        \numer=150pt
                        \denom=150pt

                        \begin{document}
                        \the\dimexpr\numer/\denom\relax% -> 0.00002pt invece di 1pt
                        \end{document}`

                        Evidentemente mi serve leggere la documentazione…
                        Ecco l’ho fatto (quella di e-TeX) 🙂
                        occorre moltiplicare per 65536 giusto?
                        \the\dimexpr\numer/\denom*65536\relax
                        tuttavia la soluzione con \pgfmath mi soddisfa.
                        Grazie.
                        Un saluto.
                        R.

                      • #76077
                        OldClaudio
                        Partecipante
                          Up
                          0
                          Down
                          ::


                          Allora con i comandi primitivi di TeX tradizionale si ottengono cose strane, e il risultato è corretto ().00002) ma manca lo scalamnento fra punti e scaled points, cosa che ha scoperto da solo
                          con \dimexpr ti sei dimenticato di seguire le indicazioni che ti avevo dato, cioè di eseguire l’operazione a/c facendo a*b/c con b pari a un punto. Il codice
                          `\documentclass{article}

                          \newdimen\numer
                          \newdimen\denom
                          \newdimen\quoz

                          \newcount\Nnumer
                          \newcount\Ndenom
                          \newcount\Nquoz

                          \makeatletter
                          \let\unpunto\p@

                          \begin{document}
                          \numer=150pt
                          \denom=150pt

                          \Nnumer=\numer \Ndenom\denom \Nquoz=\Nnumer
                          \divide\Nquoz by\Ndenom \quoz=\Nquoz\unpunto
                          \the \quoz

                          \vspace{2\baselineskip}

                          \the\dimexpr\numer*\unpunto/\denom\relax% -> 0.00002pt invece di 1pt
                          \end{document}`
                          scritto volutamente in modo ridondante, mostra esattamente quello che succede; come vedi in entrambi i casi si moltiplica per \unpunto, ma nel caso di \dimexpr non si va in overflow, mentre se usi i vecchi comandi, devi stare attento ad eseguire la moltiplicazione sul risultato finale, perché potresti andare in overflow, non sul prodotto intermedio, e così facendo potresti perdere moltissima precisione.

                          Ora il metodo di \dimexpr serve benissimo per scrivere macro in file .sty, dove non hai bisogno di eseguire l’equivalenza di \unpunto con \p@; l’operazione è velocissima perché viene eseguita dentro i registri della cpu; pdfmath risolve invece tutto quanto ricorrendo a macro, ai loro sviluppi e compagnia bella. I tempi di esecuzione di una operazione come questa potrebbero crescere a dismisura, ma anche moltiplicando per 1000 pochi nanosecondi, si ottengono pochi microsecondi, il che ai tempi nostri vuol dire tempi trascurabili; con macchine vecchiotte (io ho ancora un desktop che gira con un clock di 30MHz, non di 3GHz come le macchine moderne) la differenza si sente eccome!
                          Siccome tu usi macchine moderne, capisco che tu ti senta più a tuo agio con pgfmath, e l’aumento di cpu time per te sia trascurabile.
                          Ciao
                          Claudio

                        • #76078
                          Up
                          0
                          Down
                          ::


                          La divisione dà il risultato corretto, cioè 1sp. 🙂 Ecco qui una breve sessione interattiva:
                          `This is TeX, Version 3.1415926 (TeX Live 2012)
                          **\dimen0=150pt

                          *\divide\dimen0 by\dimen0

                          *\count255=\dimen0

                          *\showthe\count255
                          > 1.
                          <*> \showthe\count255

                          ? `
                          Ricorda che TeX fa sempre i conti in “scaled point”, ma poi mostra l’equivalente in “pt”.

                          Ciao
                          Enrico

                        • #76079
                          OldClaudio
                          Partecipante
                            Up
                            0
                            Down
                            ::


                            Come dice giustamente Enrico, TeX fa i conti con i numeri interi e internamente le lunghezze sono numeri interi di scaled points; ricorda che 1pt = 2^{16}sp; 2^{16} è quel numero magico che hai trovato anche tu: 65536.

                            Quindi se dividi due lunghezze uguali come i tuoi 150pt dell’esempio il rapporto degli scaled points vale 1, ma se lo consideri lunghezza esso vale 2^{-16}ptn, a rigore 0.00001525878906, che TeX ti arrotonda a 0.00002pt come hai giustamente trovato; ma apri la documentazione con texdoc etex e vai nella pagina 8, §3.5 Expressions e alla fine del secondo capoverso del paragrafo trovi:

                            The arithmetic operations are performed individually, except for ‘scaling’ opera- tions (a multiplication immediately followed by a division) which are performed as one combined operation with a 64-bit product as intermediate value. The result of each operation is again checked to be in the allowed range. Finally the results of divisions and scalings are rounded, whereas TEX’s \divide truncates.

                            Questo significa che nell’operazione a*b/c, lo scalamento di a per il rapporto fra b e c, b e c possono essere entrambe lunghezze o entrambi numeri interi e l’operazione viene eseguita correttamente nei due casi; mentre se semplicemente dividi a/b, che non è uno scalamento, ma il calcolo di un rapporto, il risultato del quale è una lunghezza se a è una lunghezza e b un numero intero,. è un numero intero se a e b sono entrambe lunghezze , e viene zero se a è un intero inferiore a 2^{16} e b una lunghezza maggiore di 1pt, e viene un brutto risultato intero malamente approssimato se a è grande e b è piccolo è il solito discorso del rapporto fra interi, siano essi il numero intero di scaled point o numeri interi tout court.
                            i pacchetti calc, pgfmath e simili fanno molte soe, ma le operazioni fra numeri fratti le ottengono considerando quei numeri fratti come moltiplicatori di 1pt, eseguendo le operazioni giuste sulle grandezze in scaled points, e poi togliendo dal risultato la parte pt della grandezza. Tutto questo implica una mole di calcoli enorme a confronto con le semplici operazioni all’interno della cpu cablate nelle estensioni etex.

                            Non volgio difendere queste estensioni più di tanto; infatti se devi anche solamente calcolare una distanza euclidea fra due punti nel piano, devi estrarre anche una radice quadrata che le estensioni di etex non possono fare direttamente. calc e pgfmath lo possono fare ma a spese di lunghi giri di macro; prova a caricare il pacchetto trace oltre al pacchetto pgfmath, e a racchiudere un’operazione semplice, tipo una distanza euclidea, e poi mettici a cavallo \traceon e \traceoff; fai andare l’esempio, e poi prova a leggere il file log; troverai qualcosa come il tracciamento di alcune migliaia di righe, il che ti dà l’idea della mole di operazioni necessarie. prova a implementare un semplice algoritmo di Newton per la radice quadrata da realizzare con le estensioni di etex e rifai al prova, troverai che il tracciamanto contiene un numero di righe assai inferiore e nessuna riga corrispondente alle \dimexpr che hai usato, perché sono tutti calcoli che “non interessano” TeX ma la cpu.

                        Visualizzazione 14 filoni di risposte
                        • Devi essere connesso per rispondere a questo topic.

                        Go to top