Table of contents:
initial answer about randomly choosing 1
or -1
,
first addendum about using package xinttools to more generally choose expandably among braced items. For general principle of a more efficient -- if doing many times -- package free but non expandable approach see the comments,
second addendum for the case of numerical values only will pick up(again expandably) randomly in a comma separated list using xintexpr.
initial answer
You are using anyhow pdftex named random-related utilities (\pdfrandomseed
). Simplest (and probably fastest) is just
\documentclass{article}
%\usepackage{pgf}
%\pgfmathsetseed{\number\pdfrandomseed}% not needed here
\makeatletter
\def\plusorminusone{\ifnum\pdfuniformdeviate\tw@>\z@-\fi 1}
\makeatother
\begin{document}
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\plusorminusone
\end{document}

(the code uses \tw@
, \z@
--- hence the \makeatletter
--- in a silly idea that it may be slightly faster than 2
and 0
and to not have to worry about leaving a space token to properly terminate them (here, the 0
only))
In certain contexts you may prefer the variant
\ifnum\pdfuniformdeviate\tw@>\z@\expandafter-\fi 1
or perhaps
\the\numexpr\ifnum\pdfuniformdeviate\tw@>\z@-\fi 1\relax
Also, you may be used to \pgfmathparse
type of syntax, then maybe something like this
\makeatletter
\def\plusorminusoneset #1{\edef#1{\ifnum\pdfuniformdeviate\tw@>\z@-\fi 1}}
\makeatother
\plusorminusoneset\x
\x
\plusorminusoneset\x
\x
but this looks very cumbersome to use.
first addendum
To choose expandably randomly from a (not pre-defined) list, you can use \xintNthElt
from package xinttools.
\documentclass{article}
\usepackage{xinttools}
\newcommand\myrandomelement [1]% this comment character isn't needed but pretty
{\xintNthElt{1+\pdfuniformdeviate \xintNthElt{0}{#1}}{#1}}
\begin{document}
\myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement
{ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF},
\myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement
{ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}, \myrandomelement {ABCDEF}
\end{document}

Use braces if needed: \myrandomelement {{ABC}{$1$}{\par}}
.
Remarks:
the code is expandable
the code will recompute the total number of elements each time, thus in contexts where this information is stable, it might be better to have a macro with two arguments whose second argument will be the already known number of elements,
we need to shift by one, because elements are numbered starting at one, (the 0
is used to get the number of elements...)
xinttools has some inner macros which handle rather comma separated lists and count starting at zero not at one; but they are private...
well, ok, let's be open, the macros to be used are \xintCSVNthEltPy
and \xintCSVLength
. The source code contains these comments:
We don't take any precaution here regarding brace stripping or spaces. And the macros are short. They will remain undocumented in the user manual for the time being for the reasons above and to preserve the possibility to modify the interface in case some evolution on the xintexpr side requires it. Nevertheless, directly usable names are also provided.
you can still handle comma separated values by using \xintCSVtoList
.
the list argument may be a macro it does not have to be explicit like in my example.
second addendum
When handling numerical values you can do this using the list syntax provided by the xintexpr expressions.
\documentclass{article}
\usepackage{xintexpr}
\begin{document}
\xintdeffloatvar Pi := 3.1415926535897932;
\xintdeffloatvar e := 2.7182818284590452;
\xintthefloatexpr \empty [sqrt(3), Pi, e][\pdfuniformdeviate 3]\relax
\xintthefloatexpr ([sqrt(3), Pi, e][\pdfuniformdeviate 3])\relax
\xintthefloatexpr [4]
subs(seq(([S, Pi, e][\pdfuniformdeviate 3]), i=1..10), S = sqrt(3))\relax
\end{document}
Some comments:
the \empty
is because \xintthefloatexpr
may admit an optional argument, like the [4]
in the last example which means to round the output to 4
digits of precision; the \empty
serves to calm down the (expandable) parser, as the brackets are used for something altogether different next,
in the second example, parentheses are used instead,
in the third example we want to do it ten times, but not redo the evaluation of square root of three ten times; hence we use the mechanism of substitution; the comma which separates the expression from the assigned variable must not be confused with earlier commas. Here a seq
(uence) construct hides the earlier commas, however we need to put parentheses around the list extractor, because seq
has an iteration variable (here i
) and the comma before the i
must not be mixed-up with an earlier one. I think braces may be used too, but that would need a check in the manual.

It is possible to code the last example this way:
\xintthefloatexpr [4]
subs(seq([L][\pdfuniformdeviate 3], i=1..10), L = sqrt(3), Pi, e)\relax
which has the advantage to not need extra parentheses.

\x
a value from a fixed and arbitrary set of constants?