4

The following code works great for printing new input/output values on each build to PDF; but, I cannot get it to round to any decimal place. It always rounds to the nearest integer. I have tried \numprint and \sisetup approaches with no luck. Seems like a simple problem to solve; but, I have no luck deploying answers to similar questions on this forum. Ultimately, I'd like to be able to round to the right sig figs, and have even tried that with "round-places" and "round-figures" in whatever package those are part of...no luck.

\documentclass[12pt]{article}
\usepackage{geometry}
\geometry{margin=1in}
\usepackage{pgf,amsmath,enumitem,siunitx}

\pgfmathsetseed{\number\pdfrandomseed} % seed for pseudo random generator

% new command to initialize variables
\newcommand\initVariables{%
    \pgfmathsetmacro{\A}{random(100,200)}%
    \pgfmathsetmacro{\B}{random(5,29)}%
}
% define command to calculate result
%\newcommand\answer{\pgfmathprint{round(\A / \B)}} 
\newcommand\answer{\pgfmathprint{round(\A / \B)}} 

\begin{document}
\begin{enumerate}

\initVariables % initialize variables   
    \item \textbf{An object is displaced \A \ meters in \B \ seconds.}\\ 
    \begin{equation*}
        v = \dfrac{\Delta s}{\Delta t} = \dfrac{\A \ m}{\B \ s} =
        \pgfmathparse{\A / \B}\pgfmathresult \ \frac{m}{s}
        \approx \answer \frac{m}{s}\\
    \end{equation*}

enter image description here

4
  • 4
    round is defined for integers. \pgfmathprintnumber[fixed, precision=1]{\answer} should work
    – percusse
    Commented May 1, 2018 at 14:53
  • 1. TeX capacity exceeded if I replace \answer in the equation with \pgfmathprintnumber[fixed, precision=1]{\answer}. 2. Incomplete \iffalse error anywhere outside of equation in document. 3. Package PGF Math Error: Could not parse input when using \newcommand\answer{\pgfmathprintnumber[fixed, precision=1]{\A / \B}}
    – Clark
    Commented May 1, 2018 at 17:04
  • \newcommand\answer{\pgfmathparse{\A/\B}\pgfmathprintnumber[precision=1]{\pgfmathresult}}? Commented May 1, 2018 at 20:39
  • YES! That works perfectly.
    – Clark
    Commented May 1, 2018 at 22:24

1 Answer 1

3

The expl3 kernel has a better management for floating point numbers.

The \defineVariables macro sets (locally) what the variables should contain. With \initVariables the expressions are evaluated (so random integers are actually substituted).

In order to use the variable A, use \Var{A} (it's better than using \A and so on, you risk to redefine important commands). With

\round(<expression>,<places>)

the expression is evaluated and rounded at the stated number of decimal places.

\documentclass[12pt]{article}
\usepackage{geometry}
\geometry{margin=1in}
\usepackage{amsmath,enumitem,siunitx,xfp}


\ExplSyntaxOn
% no need to set the seed with expl3

% new command to initialize variables
\NewDocumentCommand{\defineVariables}{m}
 {
  \prop_set_from_keyval:Nn \l_clark_variables_def_prop { #1 }
 }
\NewDocumentCommand{\initVariables}{}
 {
  \prop_map_inline:Nn \l_clark_variables_def_prop
   {
    \prop_put:Nnx \l_clark_variables_set_prop { ##1 } { \fp_eval:n { ##2 } }
   }
 }
\NewExpandableDocumentCommand{\Var}{m}
 {
  \prop_item:Nn \l_clark_variables_set_prop { #1 }
 }
\NewExpandableDocumentCommand{\round}{mm}
 {
  \fp_eval:n { round(#1,#2) }
 }
\prop_new:N \l_clark_variables_def_prop
\prop_new:N \l_clark_variables_set_prop
\ExplSyntaxOff

\begin{document}

\begin{enumerate}
\defineVariables{
  A={randint(100,200)},
  B={randint(5,29)},
}
\sisetup{per-mode=fraction}
% initialize variables   
\initVariables
\item \textbf{An object is displaced \Var{A} meters in \Var{B} seconds.}
  \begin{equation*}
  v = \frac{\Delta s}{\Delta t}
    = \dfrac{\SI{\Var{A}}{m}}{\SI{\Var{B}}{s}}
    = \SI{\round{\Var{A}/\Var{B}}{5}}{\meter\per\second}
    \approx \SI{\round{\Var{A}/\Var{B}}{1}}{\meter\per\second}
  \end{equation*}

% initialize variables   
\initVariables
\item \textbf{An object is displaced \Var{A} meters in \Var{B} seconds.}
  \begin{equation*}
  v = \frac{\Delta s}{\Delta t}
    = \dfrac{\SI{\Var{A}}{m}}{\SI{\Var{B}}{s}}
    = \SI{\round{\Var{A}/\Var{B}}{5}}{\meter\per\second}
    \approx \SI{\round{\Var{A}/\Var{B}}{1}}{\meter\per\second}
  \end{equation*}

% initialize variables   
\initVariables
\item \textbf{An object is displaced \Var{A} meters in \Var{B} seconds.}
  \begin{equation*}
  v = \frac{\Delta s}{\Delta t}
    = \dfrac{\SI{\Var{A}}{m}}{\SI{\Var{B}}{s}}
    = \SI{\round{\Var{A}/\Var{B}}{5}}{\meter\per\second}
    \approx \SI{\round{\Var{A}/\Var{B}}{1}}{\meter\per\second}
  \end{equation*}
\end{enumerate}
\end{document}

enter image description here

6
  • Every \initVariables line of code and every line of code with \round leads to an Undefined control sequence. Perhaps I am missing a package given that you obtained proper output? I DO like the method of defining variables much better though.
    – Clark
    Commented May 1, 2018 at 17:41
  • @Clark Are you sure your TeX distribution is up-to-date?
    – egreg
    Commented May 1, 2018 at 17:42
  • I was severely out of date; but did not realize it because everything I've been doing for the last 9 months was so routine. Updating solved the problem, and this works great. ThanX!
    – Clark
    Commented May 1, 2018 at 22:01
  • One more thing ... @egreg ... where should I look for documentation on the \ExpandableDocumentCommand structures that you've provided? The big picture aspects of that programming makes sense; but I need to catch up on a few of the details therein.
    – Clark
    Commented May 1, 2018 at 22:21
  • @Clark That's in the xparse package (automatically loaded by siunitx).
    – egreg
    Commented May 1, 2018 at 22:26

You must log in to answer this question.

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