Есть ли ограничение на начальное значение в pgfmathsetseed?

Есть ли ограничение на начальное значение в pgfmathsetseed?

Я использую pgf для создания некоторых случайных экзаменов. Для установки начального числа я использую pgfmathsetseed. Эта система использует очень разные значения начального числа, диапазон которых может достигать тысяч. В руководстве по pgf говорится, что pgfmathsetseed получает целое число, и нет ни слова о каком-либо пределе. Но я получаю абсолютно одинаковые результаты для разных начальных чисел. Следующий код иллюстрирует проблему:

\documentclass[letterpaper,9pt]{article}
\usepackage{tikz} % also for pgfmathparse
\usepackage{pgfmath} % also for pgfmathparse
\usepackage{siunitx} % also for pgfmathparse
\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}
  \pgfmathsetmacro{\FACTOR}{0.90} % constrol the randomness span
  \pgfmathrandominteger{\NA}{1}{9}
  \pgfmathsetmacro{\LAA}{2.0*(1 + \FACTOR*rand)}
  \begin{tabular}{ccc}
    #1 & \Num{\NA} & \Num{\LAA}
  \end{tabular}
}

\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}

\example{92}

\example{96}

\example{90}

\example{1}

\example{2}

\end{document}

и вывод такой

92 1.000 1.576
96 1.000 1.576
90 1.000 1.576
1 7.000 2.245
2 4.000 6.891 × 10−1

Как видите, для нескольких семян значения одинаковы. Есть ли ограничение на целое число, которое можно поместить в pgfmathsetseed? Или в чем проблема? Спасибо.

решение1

Генерация случайных чисел зависит от некоторых начальных параметров, найденных в pgfmathfunctions.random.code.tex:

\def\pgfmath@rnd@a{69621}
\def\pgfmath@rnd@r{23902}
\def\pgfmath@rnd@q{30845}

Насколько я помню (я не проверял), значения параметров были почерпнуты из Press et al.'s Numerical references in C, 2nd edition. Предлагаются альтернативы (которые также перечислены в комментариях в pgfmathfunctions.random.code.tex).

Эти параметры можно изменить, например, на те же параметры, что и у Эриха Янки.пакет lcg(на котором был основан случайный материал pgf), что может привести к более желаемым результатам (хотя повторения все еще могут происходить в последовательностях последовательных начальных чисел)

\documentclass{ltxdoc}
\usepackage{geometry}
\parindent=0pt
\usepackage{pgfmath,pgffor,lcg,xcolor,multicol}
\makeatletter
\def\pgfmath@rnd@a{16807}
\def\pgfmath@rnd@r{2836}
\def\pgfmath@rnd@q{127773}
\makeatother
\newcounter{lcgresult}
\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}%
  \reinitrand[seed=#1, counter=lcgresult, first=1, last=9]
  \xdef\pgfseq{}%
  \xdef\lcgseq{}%
  \foreach\s in{0,...,10}{%
    \pgfmathrandominteger{\r}{1}{9}
    \xdef\pgfseq{\pgfseq\space\r}
    \rand
    \xdef\lcgseq{\lcgseq\space\thelcgresult}
  }%
  \begin{tabular}{p{0.5cm}p{4cm}}
    #1\hfil & \textcolor{blue}{\pgfseq} \newline \lcgseq
  \end{tabular}%
}
\begin{document}
\begin{multicols}{3}
\foreach \i in {1,...,60}{\example{\i}}
\end{multicols}
\end{document}

введите описание изображения здесь

решение2

Кажется, здесь что-то не так: по-видимому, значима только первая цифра.

\documentclass{article}
\usepackage{geometry}
\usepackage{multicol}
\usepackage{tikz} % also for pgfmathparse
\usepackage{pgfmath} % also for pgfmathparse
\usepackage{siunitx} % also for pgfmathparse
\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}%
  \pgfmathsetmacro{\FACTOR}{0.90}% constrol the randomness span
  \pgfmathrandominteger{\NA}{1}{9}%
  \pgfmathsetmacro{\LAA}{2.0*(1 + \FACTOR*rand)}%
  #1\quad\Num{\NA}\quad\Num{\LAA}\par
}

\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}

\begin{multicols}{3}

\count255=0
\loop\ifnum\count255<120
\expandafter\example{\the\count255}
\advance\count255 1
\repeat

\end{multicols}

\end{document}

введите описание изображения здесь

Если посмотреть на таблицу, то все вызовы с аргументом, начинающимся с , 1выдают одинаковый вывод, то же самое и для 2и так далее.

С другой стороны, если я закомментирую строки, относящиеся к fpu, вывод станет таким:

введите описание изображения здесь

Случайное целое число на самом деле не кажется таким уж случайным, поскольку выбраны только 1, 4 и 7.

Вот что я получаю с expl3помощью xfp:

\documentclass{article}
\usepackage{geometry}
\usepackage{multicol}
\usepackage{siunitx,xfp}

\sisetup{round-precision=5,round-mode=figures,scientific-notation=true}

\newcommand{\FACTOR}{0.9}

\newcommand{\example}[1]{%
  \pdfsetrandomseed #1\relax
  #1\quad\num{\fpeval{randint(1,9)}}\quad\num{\fpeval{2*(1+\FACTOR*rand())}}\par
}

\begin{document}

\begin{multicols}{3}

\count255=0
\loop\ifnum\count255<120
\expandafter\example{\the\count255}
\advance\count255 1
\repeat

\end{multicols}

\end{document}

введите описание изображения здесь

решение3

Используя ответ от @Mark Wibrow, я смог улучшить случайный алгоритм (используя новые параметры для генератора, которые на самом деле взяты из второго издания Numerical Recipies), но также указать на несовместимость с fpu из pgf и настройкой seed. ПРИМЕЧАНИЕ: в моем приложении мне нужен fpu для вычисления нескольких величин, эти mwe не отображает.

Следующий пример показывает, что при активации /pgf/fpu генератор случайных чисел работает так, как и ожидалось, даже после использования улучшенных параметров. Если я деактивирую его локально, результаты будут намного лучше. Я не знаю, как именно это исправить, но каким-то образом функция pgfmathsetseed затронута и не выдает правильные данные. Вот пример

\documentclass{standalone}
\usepackage{tikz,pgfmath,pgffor,siunitx,multicol} 
\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

\pgfkeys{/pgf/fpu=true} % this breaks pgfmathsetseed

\makeatletter
\def\pgfmath@rnd@a{16807}
\def\pgfmath@rnd@r{2836}
\def\pgfmath@rnd@q{127773}
\makeatother

\newcommand{\pgfmathsetseednew}[1]{%
  \pgfkeys{/pgf/fpu=false}
  \pgfmathsetseed{#1}
  \pgfkeys{/pgf/fpu=true}
}

\newcommand{\exampleA}[1]{%
  \pgfmathsetseed{#1}%
  \pgfmathrandominteger{\r}{1}{9}
  \pgfmathsetmacro{\LAA}{2.0*(1 + 0.90*rand)}
  #1 \quad \r \quad \Num{\LAA}\par
}
\newcommand{\exampleB}[1]{%
  \pgfmathsetseednew{#1}
  \pgfmathrandominteger{\r}{1}{9}
  \pgfmathsetmacro{\LAA}{2.0*(1 + 0.90*rand)}
  #1 \quad \r \quad \Num{\LAA}\par
}
\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}
\begin{tabular}{m{0.4\textwidth}m{0.4\textwidth}}
  /pgf/fpu globally activated & /pgf/fpu locally deactivated\\
  \foreach \i in {80,...,99}{\exampleA{\i}}
  &
    \foreach \i in {80,...,99}{\exampleB{\i}}
\end{tabular}
\end{document}

и выходной сигнал

Сравнение между активированным и деактивированным fpu

Итак, в моем случае мне нужно локально деактивировать fpu. Этот ответ полностью основан на предыдущем, поэтому я думаю, что отмечу предыдущий как ответ.

решение4

Я предпочитаю использовать luaгенератор случайных чисел:

\documentclass[letterpaper,9pt]{article}
\usepackage{tikz} % also for pgfmathparse
\usepackage{pgfmath} % also for pgfmathparse
\usepackage{siunitx} % also for pgfmathparse
\usepackage{luacode,multicol}

\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}


\NewDocumentCommand{\Seed}{O{os.time( )}}{%
        \directlua{math.randomseed ( #1 ) ;}%
}

\NewDocumentCommand{\Random}{oom}{%
    % no argument :  real number between 0 and 1
    % upper : integer numbers between 1 and upper (both inclusive).
    % lower and upper : integer numbers between lower and upper
    %                                             (both inclusive).
    \IfNoValueTF{#2}{% not 2 arguments
        \IfNoValueTF{#1}{% no arguments
            \luadirect{
                t = math.random ( ) ;
            }
        }{%
            \luadirect{
                t = math.random ( #1 ) ;
            }
        }
    }{%
        \luadirect{
            t = math.random ( #1 , #2 ) ;
        }
    }
    \bgroup
        \edef\foo{\luadirect{tex.print ( t )}}
        \global\let#3=\foo
    \egroup
}


\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}
  \pgfmathsetmacro{\FACTOR}{0.90} % constrol the randomness span
%  \pgfmathrandominteger{\NA}{1}{9}
  \Random[9]{\NA}
  \Random{\Rand}
  \pgfmathsetmacro{\LAA}{2.0*(1 + \FACTOR*\Rand)}
  \begin{tabular}{ccc}
    #1 & \Num{\NA} & \Num{\LAA}
  \end{tabular}
}

\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}

\begin{multicols}{3}

\count255=0
\loop\ifnum\count255<120
\expandafter\example{\the\count255}
\advance\count255 1
\repeat

\end{multicols}

\end{document}

введите описание изображения здесь

Связанный контент