9

Faulty code:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
  \result%
}

\begin{document}
\FPset\x{2}
\FPset\y{3}
\numprint{\ratio}
\end{document}

LaTeX complains:

! Undefined control sequence. \next ->\@nil

l.14 \numprint{\ratio}

How do I evaluate \ratio and print it with \numprint?

3
  • \numprint wants to see a number, not the instructions for producing it. Can you show a more realisting situation?
    – egreg
    Oct 18, 2013 at 20:44
  • @egreg I have a macro that outputs a value which depends on previously defined variables.
    – feklee
    Oct 18, 2013 at 20:56
  • easier syntax is made possible if the computations are done expandably; egreg has now provided an l3fp approach. Using xintfrac, \numprint{\xintRound {2}{\xintDiv\x\y}}. And with xintexpr \numprint{\xinttheexpr round(\x/\y,2)\relax}. I did not make an answer because you might need functions such as sin or cos which are not at this time yet in xintexpr.
    – user4686
    Oct 19, 2013 at 7:32

4 Answers 4

9

The \numprint macro needs to be fed with a string of characters, not with the instructions to produce it. With fp, these instructions involve assignments, while \numprint is only able to process a control sequence that just expands to a number in the proper format. So the string has to be produced in advance. (Thanks to jfbu for noticing that macros can be used in the argument to \numprint, so long as they expand to strings with the proper format.)

I suggest you to define a new command that takes as argument an FP expression, possibly in a macro:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand{\numprintexpr}[2][\result]{%
  #2\relax\numprint{#1}}

\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
}

\begin{document}

\FPset\x{2}
\FPset\y{3}
\numprintexpr{\ratio}

\numprintexpr[\foo]{%
  \FPset\x{24}%
  \FPset\y{19}%
  \FPdiv\foo{\x}{\y}%
  \FPround\foo\foo{2}
}

\end{document}

The optional argument (default \result) tells \numprintexpr what control sequence stores the final result.

enter image description here


A different implementation using the fixed point facilities of expl3:

\documentclass{article}
\usepackage{xparse}
\usepackage{numprint}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\fpeval}{m}
 {
  \fp_eval:n { #1 }
 }
\NewDocumentCommand{\fpset}{mm}
 {
  \fp_zero_new:N #1
  \fp_set:Nn #1 { #2 }
 }
\cs_new_protected:Npn \feklee_numprint:n #1
 {
  \numprint { #1 }
 }
\NewDocumentCommand{\numprintexpr}{m}
 {
  \feklee_numprint:n { \fp_eval:n { #1 } }
 }
\ExplSyntaxOff

\newcommand{\ratio}{round(\x/\y,2)}

\begin{document}

\fpset\x{2}
\fpset\y{3}
\numprintexpr{\ratio}

\numprintexpr{round(pi/4,8)}

\end{document}

The syntax is different, but it's even easier than with fp.

enter image description here

7
  • Is there no way to evaluate \ratio and print it with \numprint without knowing the internals of the \ratio command?
    – feklee
    Oct 19, 2013 at 7:01
  • @feklee No, but with the suggested \numprintexpr command you don't need to know the internals, other than the scratch macro you use for storing the result: \numprint wants to see a string of characters, not the instructions for producing it. It would be different if you used the l3fp macros, that are expandable.
    – egreg
    Oct 19, 2013 at 7:06
  • Thanks for clarification! Perhaps you want to add this information to your answer.
    – feklee
    Oct 19, 2013 at 7:13
  • 1
    @feklee Check the new implementation; I know it requires changing the syntax for expressions, but I believe it's better in the long run.
    – egreg
    Oct 19, 2013 at 7:22
  • @egreg \numprint accepts completely expandable material: it is not a requirement that the input is a string of character, it may be a macro \x as long as \x expands to a string of characters in an acceptable format. (I suspect this is what you meant but beginners may have taken your sentence literally).
    – user4686
    Oct 20, 2013 at 16:38
6

pass the x/y values into the macro itself:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand\ratio[3]{%
  \FPdiv#3{#1}{#2}%
  \FPround{#3}{4}{4}}

\begin{document}
\ratio{2}{3}\result
\result

\numprint{\result}
\end{document}
1
  • You modified \ratio. That's an approach. However, I am asking for a solution to evaluate \ratio and then print the result using \numprint.
    – feklee
    Oct 18, 2013 at 22:01
2

There is already several answers to this question, but it seems that nobody suggested to use \edef. Knowing about this might be useful for you in other situations, so let me describe this alternative solution.

The \edef primitive is similar to \def but will expand the replacement text of the macro being defined. Here is how to rewrite your example:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
}

\begin{document}
\FPset\x{2}
\FPset\y{3}
\begingroup
  \ratio
  \edef\next{\noexpand\numprint{\result}%
  \expandafter
\endgroup
\next
\end{document}

See that computation and usage are now separated. The job of \ratio is limited to compute the ratio and store this in a macro.

TeX works very differently than a classical programming language where you can compose functions as you did. Indeed, it is a macro language, based on expanding and rewriting. So if you write

\numprint{\ratio}

you have absolutley no control over how the tokens produced by \ratio will be interpreted. It is easier to produce a \next macro whose replacement text is \numprint{0.67} as I did in my suggestion. Note that the whole \begingroup…\next snippet is actually replaced by \numprint{0.67} during processing.

If you are learning programming TeX, you should consider learning these methods based on \edef, \expandafter, \noexpand and registers.

4
  • In what does this differ from my answer?
    – egreg
    Oct 20, 2013 at 17:52
  • In what is this similar to your answer? It is not obvious to me so it will probably not be for the casual reader. Oct 20, 2013 at 17:54
  • I'm doing \ratio\numprint{\result} which is essentially the same, except for the group.
    – egreg
    Oct 20, 2013 at 17:57
  • As I stated it in my answer, I think that suggesting the use of \edef might be a useful addition for somebody experimenting with or learning TeX's programming system. Oct 20, 2013 at 18:02
2

You asked for a solution which keeps your original \ratio and then prints the result using \numprint. Here is how to do it:

[update: edited to avoid global assignments]

[update2: added \fFPedef macro which is necessary if one wants to go into the direction indicated at the bottom of this answer]

[update3: removed some superfluous \expandafter's]

[update4: fixed typo above (\fFPedef above was in my earlier choice \fFPset) just to move this up the list and get a chance to gather more upvotes :) ]

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

% ORIGINAL \ratio
% by convention its result is in ... \result
\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
  \result%
}

% WRAPPER to \numprint
% Must be applied to things like \ratio which compute a \result
\def\FPnumprint #1{% 
    \setbox0 \hbox{\def\result{#1}#1\expandafter}\expandafter
    \numprint\expandafter {\result}}

\begin{document}\thispagestyle{empty}
\FPset\x{2}
\FPset\y{3}

% works
\FPnumprint {\ratio}

\newcommand{\stuff}{\FPeval\result {(\x)*(\y)+(\x)^(\y)}}

% works also

\FPnumprint {\stuff}

\end{document}

Output:

numprint result

By the way one can use this kind of technique to transform all commands of fp.sty into nestable entities: (I use fFP@ prefix to mean functional form of an fp command)

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

% ORIGINAL \ratio
% by convention its result is in ... \result
\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
  \result%
}

% WRAPPER to \numprint
% Must be applied to things like \ratio which compute a \result
\def\FPnumprint #1{% 
    \setbox0 \hbox{\def\result{#1}#1\expandafter}\expandafter
    \numprint\expandafter {\result}}

\makeatletter
\def\fFPadd #1#2{%
  \setbox0 \hbox{\def\fFP@result{#1}#1\expandafter}%
  \expandafter\def\expandafter\fFP@tmpa\expandafter{\fFP@result}%
  \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
  \expandafter\def\expandafter\fFP@tmpb\expandafter{\fFP@result}%
  \FPadd\fFP@result \fFP@tmpa\fFP@tmpb 
  \fFP@result
}

\def\fFPmul #1#2{%
  \setbox0 \hbox{\def\fFP@result{#1}#1\expandafter}%
  \expandafter\def\expandafter\fFP@tmpa\expandafter{\fFP@result}%
  \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
  \expandafter\def\expandafter\fFP@tmpb\expandafter{\fFP@result}%
  \FPmul\fFP@result \fFP@tmpa\fFP@tmpb 
  \fFP@result
}

\def\fFPround #1#2{%
  \setbox0 \hbox{\def\fFP@result{#1}#1\expandafter}%
  \expandafter\def\expandafter\fFP@tmpa\expandafter{\fFP@result}%
  \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
  \expandafter\def\expandafter\fFP@tmpb\expandafter{\fFP@result}%
  \FPround\fFP@tmpb\fFP@tmpb {0}%
  \FPround\fFP@result \fFP@tmpa\fFP@tmpb
  \fFP@result
}

\def\fFPnumprint #1{%
    \setbox0 \hbox {\def\fFP@result {#1}#1\expandafter}%
    \expandafter\numprint\expandafter{\fFP@result}%
}

\makeatother

\begin{document}
\FPset\x{2}
\FPset\y{3}

% works
\FPnumprint {\ratio}

\newcommand{\stuff}{\FPeval\result {(\x)*(\y)+(\x)^(\y)}}

% works also
\FPnumprint {\stuff}

\fFPadd {\fFPmul{2}{7}}{\fFPmul{3}{7}}


\fFPround {\fFPadd{\fFPmul {3.21267}{5.277282}}{16.8927287}}{2}

\fFPround {\fFPadd{\fFPmul {3.21267}{5.277282}}{16.8927287}}{\fFPadd {1}{3}}

% !!! ATTENTION !!!
% HERE We USE \fFPnumprint as we know the "result" is in "\fFP@result" not in
% "\result"

\fFPnumprint {\fFPround {\fFPadd{\fFPmul
      {3.21267}{5.277282}}{16.8927287}}{\fFPadd {1}{3}}}

\end{document}

Output:

fFP in action

Perhaps some package could be made out of this starting point ... as fp is quite in use.


One needs in addition to the above a macro of the following type:

\makeatletter

\def\fFPedef #1#2{%
    \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
    \expandafter\edef\expandafter#1\expandafter{\fFP@result}%
}

\makeatother

\ttfamily

\fFPedef\x {\fFPmul{3.142627627}{\fFPadd{6.75272872}{7.832298292}}}
\meaning\x

Output:

fFPedef

The big difference is that as we can see here, these things are nestable.

5
  • You still need to know what the scratch macro is called; it may not be \result, for instance if you need two computations in parallel.
    – egreg
    Oct 20, 2013 at 15:45
  • @egreg The name of the scratch macro could be an optional argument defaulting to \result. In the second part of the answer I switch to \fFP@result.
    – user4686
    Oct 20, 2013 at 15:50
  • @egreg you mean two computations inside the \numprint?
    – user4686
    Oct 20, 2013 at 15:53
  • The optional argument is what I used, too. Multiple computations may be needed, using different storage macros; of course only one will store the final result and one can arrange for it to be named \result.
    – egreg
    Oct 20, 2013 at 15:56
  • @egreg one needs indeed an additional macro with the syntax \fFPprint\x{...} which will define \x to expand to the result of the (nested) computations; the difference with the original syntax of fp being that here we can nest things.
    – user4686
    Oct 20, 2013 at 15:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .