⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rand.c

📁 随机数生成器
💻 C
字号:
/**************************************************************************** Rand.C  (Random Number Generators)                                       **                                                                          ** Source file for pseudo-random number utilities.  Rand is the             ** base class for several different algorithms for generating pseudo-random ** numbers.  Any method can generate individual samples or arrays of        ** samples using "Eval".  The random seed can be reset at any time by       ** calling "Seed" with any integer.  Random permutations of the integers    ** 0,1,...(n-1) are generated by "Perm(n,P)".                               **                                                                          **   HISTORY                                                                **      Name    Date        Description                                     **                                                                          **      arvo    08/04/97    Changed to virtual functions.                   **      arvo    06/06/93    Optimization, especially for array evaluators.  **      arvo    10/06/91    Converted to C++                                **      arvo    11/20/89    Added "gen_seed" function to handle.            **      arvo    10/30/89    "state" allocation now done in rand_alloc.      **      arvo    07/08/89    Initial coding.                                 **                                                                          **--------------------------------------------------------------------------** Copyright (C) 1989, James Arvo                                           **                                                                          ** This program is free software; you can redistribute it and/or modify it  ** under the terms of the GNU General Public License as published by the    ** Free Software Foundation.  See http://www.fsf.org/copyleft/gpl.html      **                                                                          ** This program is distributed in the hope that it will be useful, but      ** WITHOUT EXPRESS OR IMPLIED WARRANTY of merchantability or fitness for    ** any particular purpose.  See the GNU General Public License for more     ** details.                                                                 **                                                                          ****************************************************************************/#include <stdio.h>#include <math.h>#include <util/Rand.h>#ifndef ABS#define ABS( x ) ((x) > 0 ? (x) : -(x))#endif/*-------------------------------------------------------------------------* * M E T H O D 1                                                           * *                                                                         * * From "Numerical Recipes," by William H. Press, Brian P. Flannery,       * * Saul A. Teukolsky, and William T. Vetterling, p. 197.                   * *                                                                         * *-------------------------------------------------------------------------*/static const long   M1 = 714025;static const long   IA =   1366;static const long   IC = 150889;static const double RM = 1.400512E-6;float RandGen_1::Eval()    {    register long  *elem;    register long  offset;    register float rand;    offset = 1 + ( 97 * index ) / M1;    if( offset > 97 ) offset = 97;    if( offset <  1 ) offset =  1;    elem   = shuffle + offset;    rand   = ( index = *elem ) * RM;    *elem  = ( seed  = ( IA * seed + IC ) % M1 );    return rand;    }void RandGen_1::Eval( int n, float *array )    {    register long *shfl = shuffle;    register long *elem;    register long offset;    for( int i = 0; i < n; i++ )         {        offset   = 1 + ( 97 * index ) / M1;        if( offset > 97 ) offset = 97;        if( offset <  1 ) offset =  1;        elem     = shfl + offset;        *array++ = ( index = *elem ) * RM;        *elem    = ( seed  = ( IA * seed + IC ) % M1 );        }    }void RandGen_1::Seed( long seed )    {    long t = ( IC + ABS( seed ) + 1 ) % M1;    for( register int k = 1; k <= 97; k++ )        {        t = ( IA * t + IC ) % M1;        shuffle[k] = ABS( t );        }    t = ( IA * t + IC ) % M1;    seed  = ABS( t );    index = ABS( t );    }/*-------------------------------------------------------------------------* * M E T H O D 2                                                           * *                                                                         * * From "The Multiple Prime Random Number Generator," by Alexander Haas,   * * ACM Transactions on Mathematical Software, Vol. 13, No. 4, December     * * 1987, pp. 368-381.                                                      * *                                                                         * *-------------------------------------------------------------------------*/float RandGen_2::Eval()    {    if( (m += 7    ) >=   9973 ) m -=  9871;    if( (i += 1907 ) >=  99991 ) i -= 89989;    if( (j += 73939) >= 224729 ) j -= 96233;    r = ((r * m + i + j) % 100000) / 10;    return r * 1.00010001E-4;    }void RandGen_2::Eval( int n, float *array )    {    for( register int k = 0; k < n; k++ )         {        if( (m += 7    ) >=   9973 ) m -=  9871;        if( (i += 1907 ) >=  99991 ) i -= 89989;        if( (j += 73939) >= 224729 ) j -= 96233;        r = ((r * m + i + j) % 100000) / 10;        *array++ = r * 1.00010001E-4;        }    }void RandGen_2::Seed( long seed )    {    r = ABS( seed      );    m = ABS( seed *  7 );    i = ABS( seed * 11 );    j = ABS( seed * 13 );    if( m < 100    ) m += 100;    if( i < 10000  ) i += 10000;    if( j < 128000 ) j += 128000;    }/*-------------------------------------------------------------------------* * M E T H O D 3                                                           * *                                                                         * * From "A More Portable Fortran Random Number Generator," by Linus        * * Schrage, ACM Transactions on Mathematical Software, Vol. 5, No, 2,      * * June 1979, pp. 132-138.                                                 * *                                                                         * *-------------------------------------------------------------------------*/static const long A3 = 16807;static const long P3 = 2147483647;float RandGen_3::Eval()    {    long xhi    = ix >> 16;    long xalo   = ( ix & 0xFFFF ) * A3;    long leftlo = xalo >> 16;    long fhi    = xhi * A3 + leftlo;    long k      = fhi >> 15;    ix          = ( ((xalo - (leftlo << 16)) - P3) +                    ((fhi - (k << 15)) << 16) ) + k;    if( ix < 0 ) ix += P3;    return ix * 4.656612875E-10;    }void RandGen_3::Eval( int n, float *array )    {    register long xhi, xalo, leftlo;    register long fhi, k;    for( register int i = 0; i < n; i++ )         {        xhi    = ix >> 16;        xalo   = ( ix & 0xFFFF ) * A3;        leftlo = xalo >> 16;        fhi    = xhi * A3 + leftlo;        k      = fhi >> 15;        ix     = ( ((xalo - (leftlo << 16)) - P3) +                   ((fhi - (k << 15)) << 16) ) + k;        if( ix < 0 ) ix += P3;        *array++ = ix * 4.656612875E-10;        }    }void RandGen_3::Seed( long seed )    {    ix = ABS( seed );    }/*-------------------------------------------------------------------------* * R A N D : : P E R M        (Permutation)                                * *                                                                         * * This routine fills an integer array of length "len" with a random       * * permutation of the integers 0, 1, 2, ... (len-1).                       * *                                                                         * * For efficiency, the random numbers are generated in batches of up to    * * "Nmax" at a time.  The constant Nmax can be set to any value >= 1.      * *                                                                         * *-------------------------------------------------------------------------*/static const int Nmax = 20;void RandGen::Perm( int len, int perm[] )    {    float R[ Nmax ];    // A buffer for getting random numbers.    int   L = len - 1;  // Total number of random numbers needed.    int   N = 0;        // How many to generate when we call Eval.    int   n = 0;        // The array index into R.    // First initialize the array "perm" to the identity permutation.    for( int j = 0; j < len; j++ ) perm[j] = j;    // Now swap a random element in the front with the i'th element.    // When i gets down to 0, we're done.    for( int i = len - 1; i > 0; i-- )   // Element i is a swap candidate.        {        if( n == N )                     // Generate more random numbers.            {            N = ( L < Nmax ) ? L : Nmax; // Can't get more than "Nmax".            Eval( N, R );                // Generate N random numbers.            L -= N;                      // Decrement total counter.            n  = 0;                      // Start index at beginning of R.            }        float r = ( i + 1 ) * R[ n++ ];  // Pick a float in [0,i+1].        int   k = (int)r;                // Truncate r to an integer.        if( k < i )                      // Disregard k == i and k == i+1.            {            int tmp = perm[i];           // Swap elements i and k.            perm[i] = perm[k];            perm[k] = tmp;            }        }    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -