在以下 MWE 中,我使用 \lhead{\stepcounter{step}\arabic{step}},它运行完美,每页递增 1。我还使用 \chead{\setrand{100}\arabic{rand}},每页都得到相同的数字。如果我在页面上的某个地方调用 \setrand,它就会起作用。如果它正在检查 rand 的值,为什么不检查 step 的值?
\documentclass{article}
\usepackage{fancyhdr}
\makeatletter
% The following is taken from \cite{Numerical Recipes in C}.
% The resulting MAX_RAND = 134456
% Proven good statistics (relatively speaking) but designed for speed.
% Uses 8 entry shuffle.
% Output through counter rand
%
% \randinit required for initialization
% \setrand{n} outputs rand between 0 and (n-1)
% \nextrand uses same scale computed by last \setrand
\newcounter{rand}%scaled random number
\newcounter{index}% used by shuffle
\global\newcount\idum
\global\newcount\im
\global\newcount\ia
\global \newcount\ic
\im = 134456\relax
\ia = 8121\relax
\ic = 28411\relax
\newcount\temp
\def\step@rand{% computes next value for \idum (internal only)
\multiply\idum by\ia
\advance\idum by\ic
\temp = \idum% compute idum mod im
\divide\temp by\im
\multiply\temp by\im
\advance\idum by -\temp
}
\global\newcount\shuffle
\shuffle = 16807\relax
\global\newcount\storeA
\global\newcount\storeB
\global\newcount\storeC
\global\newcount\storeD
\global\newcount\storeE
\global\newcount\storeF
\global\newcount\storeG
\global\newcount\storeH
\def\shuffle@rand{% random shuffle (internal only)
\step@rand
\c@index = \idum
\step@rand
\divide\c@index by\shuffle
\advance\c@index by 1
\c@rand = \csname store\Alph{index}\endcsname
\csname store\Alph{index}\endcsname = \idum
}
\newcommand{\randinit}{% required to initialize PRNG
\idum = \day
\multiply\idum by 1440\relax
\advance\idum by \time
\step@rand%warmup
\step@rand
\step@rand
\step@rand
\storeA = \idum% fill shuffle array
\step@rand
\storeB = \idum
\step@rand
\storeC = \idum
\step@rand
\storeD = \idum
\step@rand
\storeE = \idum
\step@rand
\storeF = \idum
\step@rand
\storeG = \idum
\step@rand
\storeH = \idum
}
\global\newcount\scale
\newcommand{\setrand}[1]{% scales rand between 0 and (#1 -1)
\scale = 1\relax
\ifnum #1 > 0%check for valid #1
\scale = \im
\divide\scale by #1\relax
\fi
\shuffle@rand
\divide\c@rand by\scale
}
\newcommand{\nextrand}{% uses same scale as before
\shuffle@rand
\divide\c@rand by\scale
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatother
\newcounter{step}
\begin{document}
\randinit
\pagestyle{fancyplain}
\lhead{\stepcounter{step}\arabic{step}}
\chead{\setrand{100}\arabic{rand}}
\setrand{100}\arabic{rand}\par
\setrand{100}\arabic{rand}\par
\setrand{100}\arabic{rand}\par
\setrand{100}\arabic{rand}\par
\setrand{100}\arabic{rand}\par
\setrand{100}\arabic{rand}\par
\newpage
This page intentionally left blank.
\newpage
This page intentionally left blank.
\end{document}
答案1
\global
您在不需要的地方使用它,而在需要的地方却没有使用它!
标题是按组计算的,因此\setrand
总是从头开始,当然,结果也一样。始终使用全局分配。
\documentclass{article}
\usepackage[
paperheight=6cm,
paperwidth=10cm,
margin=.5cm,
includehead,
includefoot
]{geometry}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[C]{\setrand{100}\arabic{rand}}
\fancyfoot[C]{\thepage}
\makeatletter
% The following is taken from \cite{Numerical Recipes in C}.
% The resulting MAX_RAND = 134456
% Proven good statistics (relatively speaking) but designed for speed.
% Uses 8 entry shuffle.
% Output through counter rand
%
% \randinit required for initialization
% \setrand{n} outputs rand between 0 and (n-1)
% \nextrand uses same scale computed by last \setrand
\newcounter{rand}%scaled random number
\newcounter{index}% used by shuffle
\newcount\idum
\newcount\im
\newcount\ia
\newcount\ic
\im = 134456
\ia = 8121
\ic = 28411
\newcount\temp
\def\step@rand{% computes next value for \idum (internal only)
\global\multiply\idum by\ia
\global\advance\idum by\ic
\global\temp = \idum% compute idum mod im
\global\divide\temp by\im
\global\multiply\temp by\im
\global\advance\idum by -\temp
}
\newcount\shuffle
\shuffle = 16807
\newcount\storeA
\newcount\storeB
\newcount\storeC
\newcount\storeD
\newcount\storeE
\newcount\storeF
\newcount\storeG
\newcount\storeH
\def\shuffle@rand{% random shuffle (internal only)
\step@rand
\c@index = \idum
\step@rand
\global\divide\c@index by\shuffle
\global\advance\c@index by \@ne
\global\c@rand = \csname store\Alph{index}\endcsname
\global\csname store\Alph{index}\endcsname = \idum
}
\newcommand{\randinit}{% required to initialize PRNG
\global\idum = \day
\global\multiply\idum by 1440
\global\advance\idum by \time
\global\step@rand%warmup
\step@rand
\step@rand
\step@rand
\global\storeA = \idum% fill shuffle array
\step@rand
\global\storeB = \idum
\step@rand
\global\storeC = \idum
\step@rand
\global\storeD = \idum
\step@rand
\global\storeE = \idum
\step@rand
\global\storeF = \idum
\step@rand
\global\storeG = \idum
\step@rand
\global\storeH = \idum
}
\newcount\scale
\newcommand{\setrand}[1]{% scales rand between 0 and (#1 -1)
\global\scale = \@ne
\ifnum #1 > \z@ %check for valid #1
\global\scale = \im
\global\divide\scale by #1\relax
\fi
\shuffle@rand
\divide\c@rand by\scale
}
\newcommand{\nextrand}{% uses same scale as before
\shuffle@rand
\global\divide\c@rand by\scale
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatother
\begin{document}
\randinit
\setrand{100}\arabic{rand}
\setrand{100}\arabic{rand}
\setrand{100}\arabic{rand}
\setrand{100}\arabic{rand}
\setrand{100}\arabic{rand}
\setrand{100}\arabic{rand}
\setrand{100}\arabic{rand}
\newpage
This page intentionally left blank.
\newpage
This page intentionally left blank.
\end{document}
在诸如 之类的声明中\global\newcount\idum
,\global
它们是多余的,因为它们位于最外层。它没有意味着后续操作\idum
是全局的。诸如
\multiply\idum by\ia
是局部的(除非在为正时进行处理\globaldefs
,但这是相当深奥的),因此一旦它出现的组结束,其效果就会被取消。如果你想在\idum
全球范围内进行操作,你有\global
在作业前面添加,所以
\global\multiply\idum by\ia
其他作业也同样如此。
请注意,LaTeX 计数器上的基本操作(例如)rand
是全局的,因为\stepcounter{rand}
扩展为\global\advance\c@rand\@ne
。
一般来说,总是在本地或总是在全局对寄存器进行编程操作是更好的选择,因为对同一个变量进行本地赋值后再进行全局赋值会耗尽 TeX 用于撤消本地赋值的堆栈中的位置。
在这种特殊情况下,最好全局执行操作。这可能不是所有计算都需要的,但应该对算法进行更深入的分析。例如,如果寄存器仅用于临时存储,则对它的操作最好是本地的。