【问题标题】:What common algorithms are used for C's rand()?C 的 rand() 使用了哪些常用算法?
【发布时间】:2010-11-04 19:24:36
【问题描述】:

据我了解,C 规范并没有给出任何关于rand() 的具体实现的规范。不同的主要平台常用哪些不同的算法?它们有何不同?

【问题讨论】:

  • 主要评论是 rand() 只是伪随机数,通常甚至不是一个非常好的伪随机数生成器。 C 标准提出了一种可能的实现,许多实现都使用它。正如其他人所指出的,还有很多其他的。只需确保在需要加密随机性的情况下不要使用基本随机函数即可。

标签: c algorithm random platform


【解决方案1】:

见这篇文章: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”

【讨论】:

  • 就这样?出乎意料的简单。非常感谢。
  • 是的,就是这样,大多数通用 PNRG 的实现都非常简单。如果您正在寻找更复杂的东西,请尝试 Mersenne Twister。
  • 即使是 MT19937 也不难实现。
  • 通过@Tiemen 下面:@Aaron 我无法评论,但 RAND_MAX 是返回的最高可能值,而不是重复之前的迭代次数。
  • @Jason:有链接吗?我的印象是 RAND_MAX 调用不会重复(当然,除非您更改种子)
【解决方案2】:

我曾经为一门离散数学课程写过关于 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;
}

【讨论】:

  • Microsoft C 运行时库的 C 源代码作为 MSDN 的一部分提供,其中包含 rand()/srand()。例如,在此处查看 microsoft_rand 的可移植实现:bitbucket.org/shlomif/fc-solve/src/… /board_gen/pi_make_microsoft_freecell_board.c?at=master(短 URL - is.gd/kAUmHW
【解决方案3】:

PRNG(伪随机数生成器)领域相当广阔。

首先,您必须了解,如果没有外部输入(通常是物理输入),您无法获得随机数的真实来源。这就是为什么这些算法被称为 伪随机:它们通常使用种子来初始化一个很长的序列中的位置,该序列似乎是随机的,但它根本不是随机的。

最简单的算法之一是线性同余生成器 (LCG),它有一些约束来保证长序列,而且它根本不安全。

另一个有趣的(至少就名字而言)是 Blum Blum Shub 生成器 (BBS),这对于普通 PRNG 来说是不寻常的,因为它依赖于模算术中的幂运算,从而提供与 RSA 和 El Gamal 等其他算法相当的安全性打破序列(如果我不确定它的证明)

【讨论】:

    【解决方案4】:

    如果您需要特定的或更高级的东西,您可以将 Boost Random 库用于不同的随机数生成器。

    Boost Random 的文档是here

    【讨论】:

    • 这是一道 C 题,不是 C++,boost 不能用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 2015-05-22
    • 2011-06-14
    • 2014-04-15
    • 2011-02-26
    • 2012-11-12
    • 2011-02-26
    相关资源
    最近更新 更多