我知道 C 规范没有给出任何关于rand()
. 不同的主要平台常用哪些不同的算法?它们有何不同?
4 回答
见这篇文章:http ://en.wikipedia.org/wiki/List_of_random_number_generators
这是 glibc 的源代码rand()
:
/* Reentrant random function from POSIX.1c.
Copyright (C) 1996, 1999, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stdlib.h>
/* This algorithm is mentioned in the ISO C standard, here extended
for 32 bits. */
int
rand_r (unsigned int *seed)
{
unsigned int next = *seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int) (next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int) (next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int) (next / 65536) % 1024;
*seed = next;
return result;
}
来源:https ://sourceware.org/git/?p=glibc.git;a=blob_plain;f=stdlib/rand_r.c;hb=HEAD
如您所见,它只是简单地乘以加法和移位。这些值是经过仔细选择的,以确保您不会重复 RAND_MAX 迭代的输出。
请注意,这是一个旧实现,已被更复杂的算法取代:https ://sourceware.org/git/?p=glibc.git;a=blob_plain;f=stdlib/random_r.c;hb=HEAD
如果链接损坏,请谷歌搜索“glibc rand_r”
我曾经为一门离散数学课程写过关于 CRNG 的报告。为此,我在 msvcrt.dll 中反汇编了 rand():
msvcrt.dll:77C271D8 mov ecx, [eax+14h]
msvcrt.dll:77C271DB imul ecx, 343FDh
msvcrt.dll:77C271E1 add ecx, 269EC3h
msvcrt.dll:77C271E7 mov [eax+14h], ecx
msvcrt.dll:77C271EA mov eax, ecx
msvcrt.dll:77C271EC shr eax, 10h
msvcrt.dll:77C271EF and eax, 7FFFh
所以这是一个 LCG 之类的东西(未经测试)......
int ms_rand(int& seed)
{
seed = seed*0x343fd+0x269EC3; // a=214013, b=2531011
return (seed >> 0x10) & 0x7FFF;
}
PRNG(伪随机数生成器)领域非常广阔。
首先,您必须了解,如果没有外部输入(通常是物理输入),您将无法获得真正的随机数来源。这就是这些算法被称为伪随机的原因:它们通常使用种子来初始化一个位置很长的序列,看起来是随机的,但根本不是随机的。
最简单的算法之一是线性同余生成器( LCG ),它有一些成本约束来保证长序列,而且它根本不安全。
另一个有趣的(至少就名字而言)是 Blum Blum Shub 生成器 ( BBS ),这对于普通 PRNG 来说是不寻常的,因为它依赖于模算术中的幂运算,在破坏序列方面提供了与 RSA 和 El Gamal 等其他算法相当的安全性(如果我不确定它的证明)
如果您需要特定的或更高级的东西,您可以将 Boost Random 库用于不同的随机数生成器。
Boost Random 的文档在这里。