나는 임의의 시험을 만들기 위해 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.의 C, 2판 수치 참조에서 수집되었습니다. 대안이 제안됩니다(의 설명에도 나열되어 있음 pgfmathfunctions.random.code.tex
).
예를 들어 이러한 매개변수는 Erich Janka의 매개변수와 동일한 매개변수로 변경될 수 있습니다.LCD 패키지(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
동일한 출력을 생성하며 for 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의 두 번째 버전에서 나온 생성기에 대한 새로운 매개변수를 사용하여)을 개선할 수 있었을 뿐만 아니라 pgf의 fpu와의 비호환성도 지적할 수 있었습니다. 그리고 씨앗의 세팅. 참고: 내 응용 프로그램에서는 여러 수량을 계산하기 위해 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를 로컬에서 비활성화해야 합니다. 이 답변은 전적으로 이전 답변을 기반으로 하기 때문에 이전 답변을 답변으로 표시할 것 같습니다.
답변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}