# Latex dynamically named macro doesn't work

In this MWE, \Nba is not created. How to have it ?

Edit Remplacing \newcommand by \gdef makes \Nba exist but gives fantaisist value ? Any idea ?

\documentclass[10pt,a4paper,french]{article}
\usepackage{tikz,xstring}

\pgfmathsetseed{\number\pdfrandomseed}

\newcommand{\Range}[2]{%
\xdef\NbMin{#1}%
\xdef\NbMax{#2}%
}

\newcommand{\Numbers}[1]{%
\foreach \i in {#1} {%
%
\StrGobbleLeft{\i}{1}[\Decimal]
\StrLeft{\i}{1}[\Letter]
%
\IfStrEq{\Decimal}{}{%
% integer in the range
\pgfmathparse{int(\NbMin+random()*(\NbMax-\NbMin))}%
}{%
% décimal in the range
\pgfmathparse{%
round((\NbMin+random()*(\NbMax-\NbMin))*10^\Decimal)/10^\Decimal}%
} % \pgfmathprintnumber -- problème d'arrondi
\Letter\ -- \pgfmathprintnumber{\pgfmathresult}%
\expandafter\newcommand\csname Nb\Letter\endcsname{%
\pgfmathprintnumber{\pgfmathresult}}
}
}

\begin{document}

\Range{-10}{10}
\Numbers{a1,b,c3}

% \Nba

\end{document}
• \Nba isn't known in the loop already – user31729 Jul 14 '15 at 20:15
• My question is how to create dynamically \Nba, the loop has to create it. – Tarass Jul 14 '15 at 20:16
• Yes, I understood that. But even at the end of the current loop state, the \Nba or \Nbb etc. macros aren't defined already, so it's hopeless to expect, they would be visible outside – user31729 Jul 14 '15 at 20:20
• Why ? I use the methode seen in the answer here : tex.stackexchange.com/questions/64015/…. If it's not relevant how to do that ? – Tarass Jul 14 '15 at 20:26
• @Tarass It would be nice to know what's the expected result and what's the syntax you're using. I'm pretty sure this can be coded more easily. – egreg Jul 14 '15 at 21:25

A wild guess: you want that \Numbers{c3} defines a macro \Nbc that stores a random number in the specified range, with three decimal digits, an integer if no number is specified.

Here's an expl3 implementation that relies on pdflatex for generating random numbers.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\Range}{mm}
{
\int_gset:Nn \g_tarass_nb_min_int { #1 }
\int_gset:Nn \g_tarass_nb_max_int { #2 }
}
\NewDocumentCommand{\Numbers}{m}
{
\clist_map_inline:on { #1 }
{
\tarass_process_numbers:n { ##1 }
}
}

\int_new:N \g_tarass_nb_min_int
\int_new:N \g_tarass_nb_max_int

\cs_new_protected:Npn \tarass_process_numbers:n #1
{
\tl_if_empty:xTF { \tl_tail:n { #1 } }
{
\tarass_process_item:nn { #1 } { 0 }
}
{
\tarass_process_item:xx { \tl_head:n { #1 } } { \tl_tail:n { #1 } }
}
}

\cs_new_protected:Npn \tarass_process_item:nn #1 #2
{
\cs_new:cpx { Nb#1 }
{
\fp_eval:n
{
round
(
\g_tarass_nb_min_int +
\tarass_random:n { \g_tarass_nb_max_int - \g_tarass_nb_min_int }
, #2
)
}
}
}

\cs_new:Npn \tarass_random:n #1
{
\fp_eval:n
{
(
( \pdfuniformdeviate \c_ten_thousand )/\c_ten_thousand
) * (#1)
}
}

\cs_generate_variant:Nn \tarass_process_item:nn { xx }
\cs_generate_variant:Nn \tl_if_empty:nTF { x }
\cs_generate_variant:Nn \clist_map_inline:nn { o }

\ExplSyntaxOff

\begin{document}

\Range{-10}{10}
\Numbers{a1,b,c3}

$\Nba$ $\Nbb$ $\Nbc$

\end{document}

Change \c_ten_thousand into a bigger number, if you need higher precision.

• c3 means a decimal in the range with 3 decimal digits (max), your code seams to give a décimal one non null digit on the third place after the decimal point. I tried to correct this, I can't. I my example c3 coud be 8.123 . b is an integer, could be -10. – Tarass Jul 15 '15 at 7:22
• @Tarass I'm just too weak in numeric math. If you have a good idea about getting a decimal number in the specified range, I'll be happy to try and implement it. – egreg Jul 15 '15 at 7:24
• If I try \xdef\List{a1,b,c3}, then \Numbers{\List} gives ! Undefined control sequence. <recently read> \Nba – Tarass Jul 15 '15 at 7:24
• @Tarass Of course. I can't read your mind, can I? Finally, I find this a very bad way to set things. – egreg Jul 15 '15 at 7:25
• the formula is correct in my example :  round((\NbMin+random()*(\NbMax-\NbMin))*10^\Decimal)/10^\Decimal} but I mess to transpose it in your code. – Tarass Jul 15 '15 at 7:26

Writing the new command as Nb\Letter is not the standard way, \gdef expects a \name and not name\Letter. So I defined \Nba as \def\Nba{Nb\Letter}.

\documentclass[10pt,a4paper]{article}
\usepackage{tikz,xstring}
\pgfmathsetseed{\number\pdfrandomseed}

\def\Range#1#2{%
\xdef\NbMin{#1}%
\xdef\NbMax{#2}%
}
\def\Numbers#1{%
\foreach \i in {#1} {%
\StrGobbleLeft{\i}{1}[\Decimal]
\StrLeft{\i}{1}[\Letter]
%
\IfStrEq{\Decimal}{}{%
% integer in the range
\pgfmathparse{int(\NbMin+random()*(\NbMax-\NbMin))}%
}{%
% décimal in the range
\def\Nba{Nb\Letter}
\pgfmathparse{%
round((\NbMin+random()*(\NbMax-\NbMin))*10^\Decimal)/10^\Decimal}%
} % \pgfmathprintnumber -- problème d'arrondi
\Letter\ -- \pgfmathprintnumber{\pgfmathresult}%
\Nba\ -- \pgfmathprintnumber{\pgfmathresult}%
}
}
\begin{document}
\Range{-10}{10}
\Numbers{a1,b1,c3}
%\Nba
\end{document}

• If works for \Nba but the loop has to create \Nbb and \Nbc. – Tarass Jul 14 '15 at 20:40
• And in your example \Nba should be -8.6 instead of 1.21*10^50. – Tarass Jul 14 '15 at 20:42
• Are the updated numbers correct? and what should be Nba,Nbb,Nbc? – AboAmmar Jul 14 '15 at 21:00
• The loop calculate randomelly a value for each a, b, c : a1 mean a decimal with one décimal, b means integer, c2 means to décimal. This values are the value you see at the end of the loop. In your example a is -3.2, b -7 and c -2.18. \Nbx should store this values for ulterieur reuse. – Tarass Jul 14 '15 at 21:04
• @Tarass : \Nba is known only inside the loop. It prints normally inside the loop as you see. Also the argument b should be b0, b1, b3.. – AboAmmar Jul 14 '15 at 21:16