Ich verwende pgf, um einige zufällige Prüfungen zu erstellen. Um den Seed festzulegen, verwende ich pgfmathsetseed. Dieses System verwendet sehr unterschiedliche Werte für den Seed, deren Bereich bis in die Tausende gehen kann. Im pgf-Handbuch steht, dass pgfmathsetseed eine Ganzzahl empfängt, und es gibt kein Wort über eine Begrenzung. Aber ich erhalte genau die gleichen Ergebnisse für verschiedene Seeds. Der folgende Code veranschaulicht das Problem:
\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}
und die Ausgabe ist wie
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
Wie Sie sehen, sind die Werte für mehrere Seeds gleich. Gibt es eine Grenze für die Ganzzahl, die in pgfmathsetseed eingegeben werden kann? Oder wo liegt das Problem? Danke.
Antwort1
Die Erzeugung von Zufallszahlen hängt von einigen Anfangsparametern ab, die in folgenden Elementen zu finden sind pgfmathfunctions.random.code.tex
:
\def\pgfmath@rnd@a{69621}
\def\pgfmath@rnd@r{23902}
\def\pgfmath@rnd@q{30845}
Soweit ich mich erinnere (ich habe es nicht überprüft), wurden die Parameterwerte aus Press et al.s Numerical References in C, 2. Auflage, entnommen. Es werden Alternativen vorgeschlagen (die auch in den Kommentaren in aufgeführt sind pgfmathfunctions.random.code.tex
).
Diese Parameter können beispielsweise in die gleichen Parameter wie Erich Jankas geändert werden.lcg-Paket(auf dem das zufällige PGF-Material basierte), was zu wünschenswerteren Ergebnissen führen könnte (obwohl es in Sequenzen aufeinanderfolgender Seeds immer noch zu Wiederholungen kommen kann)
\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}
Antwort2
Hier scheint etwas nicht zu stimmen: Anscheinend ist nur die erste Ziffer von Bedeutung.
\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}
Wenn wir uns die Tabelle ansehen, erzeugen alle Aufrufe, deren Argument mit beginnt, 1
dieselbe Ausgabe und dasselbe für 2
usw.
Wenn ich andererseits die Zeilen im Zusammenhang mit auskommentiere fpu
, wird die Ausgabe
Die zufällige Ganzzahl scheint nicht wirklich so zufällig zu sein, da nur 1, 4 und 7 ausgewählt werden.
Folgendes erhalte ich mit expl3
via 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}
Antwort3
Mithilfe der Antwort von @Mark Wibrow konnte ich sowohl den Zufallsalgorithmus verbessern (indem ich die neuen Parameter für den Generator verwendete, die eigentlich aus der zweiten Ausgabe von Numerical Recipies stammen), als auch auf die Inkompatibilität mit der FPU von PGF und der Einstellung des Seeds hinweisen. HINWEIS: In meiner Anwendung brauche ich die FPU, um mehrere Mengen zu berechnen, diese MWE zeigt dies nicht an.
Das folgende Beispiel zeigt, dass wenn /pgf/fpu aktiviert ist, der Zufallszahlengenerator auch nach Verwendung der verbesserten Parameter wie erwartet funktioniert. Wenn ich es lokal deaktiviere, sind die Ergebnisse deutlich besser. Ich weiß nicht genau, wie ich das beheben kann, aber irgendwie ist die Funktion pgfmathsetseed betroffen und produziert nicht die richtigen Daten. Hier ist das Beispiel
\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}
und die Ausgabe ist
In meinem Fall muss ich die FPU also lokal deaktivieren. Diese Antwort basiert vollständig auf der vorherigen, daher werde ich die vorherige wohl als Antwort markieren.
Antwort4
Ich bevorzuge die Verwendung eines lua
Zufallszahlengenerators:
\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}