27

私は、C 仕様が の特定の実装に関する仕様を提供していないことを理解していrand()ます。さまざまな主要プラットフォームで一般的に使用されているさまざまなアルゴリズムは何ですか? それらはどのように異なりますか?

4

4 に答える 4

24

この記事を参照してください: 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

リンクが壊れている場合は、Google で「glibc rand_r」を検索してください

于 2009-06-22T10:00:24.830 に答える
13

以前、離散数学のコースで 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;
}
于 2009-08-15T00:03:49.690 に答える
3

PRNG (疑似乱数ジェネレーター) の分野は非常に広大です。

まず最初に、外部入力 (通常は物理的) がなければ、乱数の実際のソースを取得できないことを理解しなければなりません。これが、これらのアルゴリズムが疑似ランダムと呼ばれる理由です。通常、シードを使用して位置を初期化します。ランダムに見える非常に長いシーケンスですが、まったくランダムではありません。

最も単純なアルゴリズムの 1 つはLinear Congruential Generator ( LCG ) です。これには、長いシーケンスを保証するためのいくつかの制約があり、まったく安全ではありません。

もう 1 つの面白いもの (少なくとも名前については) は Blum Blum Shub Generator ( BBS ) です。これは通常の PRNG では珍しいもので、モジュロ演算の累乗に依存しており、シーケンスを破る際に RSA や El Gamal などの他のアルゴリズムに匹敵するセキュリティを提供します (また、その証拠について確信が持てない場合)

于 2009-06-22T23:24:23.143 に答える
2

特定の、またはより高度な何かが必要な場合は、さまざまな乱数ジェネレーターに Boost Random ライブラリを使用できます。

Boost Random のドキュメントはこちらです。

于 2009-06-22T10:04:40.453 に答える