免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5279 | 回复: 9
打印 上一主题 下一主题

[函数] 随机函数Random如何写? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-03-29 17:03 |只看该作者 |倒序浏览
一直在想随机函数用什么算法写,有哪位大哥可以告诉我原理吗? 最好写出来

论坛徽章:
0
2 [报告]
发表于 2006-03-29 17:55 |只看该作者
不会,不过光想就很困难了,何况去写.估计在这里你很难找到答案

论坛徽章:
0
3 [报告]
发表于 2006-03-29 18:04 |只看该作者
看看行不行?

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. /*
  4. * random.c:
  5. * An improved random number generation package.  In addition to the standard
  6. * rand()/srand() like interface, this package also has a special state info
  7. * interface.  The initstate() routine is called with a seed, an array of
  8. * bytes, and a count of how many bytes are being passed in; this array is then
  9. * initialized to contain information for random number generation with that
  10. * much state information.  Good sizes for the amount of state information are
  11. * 32, 64, 128, and 256 bytes.  The state can be switched by calling the
  12. * setstate() routine with the same array as was initiallized with initstate().
  13. * By default, the package runs with 128 bytes of state information and
  14. * generates far better random numbers than a linear congruential generator.
  15. * If the amount of state information is less than 32 bytes, a simple linear
  16. * congruential R.N.G. is used.
  17. * Internally, the state information is treated as an array of longs; the
  18. * zeroeth element of the array is the type of R.N.G. being used (small
  19. * integer); the remainder of the array is the state information for the
  20. * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
  21. * state information, which will allow a degree seven polynomial.  (Note: the
  22. * zeroeth word of state information also has some other information stored
  23. * in it -- see setstate() for details).
  24. * The random number generation technique is a linear feedback shift register
  25. * approach, employing trinomials (since there are fewer terms to sum up that
  26. * way).  In this approach, the least significant bit of all the numbers in
  27. * the state table will act as a linear feedback shift register, and will have
  28. * period 2^deg - 1 (where deg is the degree of the polynomial being used,
  29. * assuming that the polynomial is irreducible and primitive).  The higher
  30. * order bits will have longer periods, since their values are also influenced
  31. * by pseudo-random carries out of the lower bits.  The total period of the
  32. * generator is approximately deg*(2**deg - 1); thus doubling the amount of
  33. * state information has a vast influence on the period of the generator.
  34. * Note: the deg*(2**deg - 1) is an approximation only good for large deg,
  35. * when the period of the shift register is the dominant factor.  With deg
  36. * equal to seven, the period is actually much longer than the 7*(2**7 - 1)
  37. * predicted by this formula.
  38. */



  39. /*
  40. * For each of the currently supported random number generators, we have a
  41. * break value on the amount of state information (you need at least this
  42. * many bytes of state info to support this random number generator), a degree
  43. * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
  44. * the separation between the two lower order coefficients of the trinomial.
  45. */

  46. #define                TYPE_0                0                /* linear congruential */
  47. #define                BREAK_0                8
  48. #define                DEG_0                0
  49. #define                SEP_0                0

  50. #define                TYPE_1                1                /* x**7 + x**3 + 1 */
  51. #define                BREAK_1                32
  52. #define                DEG_1                7
  53. #define                SEP_1                3

  54. #define                TYPE_2                2                /* x**15 + x + 1 */
  55. #define                BREAK_2                64
  56. #define                DEG_2                15
  57. #define                SEP_2                1

  58. #define                TYPE_3                3                /* x**31 + x**3 + 1 */
  59. #define                BREAK_3                128
  60. #define                DEG_3                31
  61. #define                SEP_3                3

  62. #define                TYPE_4                4                /* x**63 + x + 1 */
  63. #define                BREAK_4                256
  64. #define                DEG_4                63
  65. #define                SEP_4                1


  66. /*
  67. * Array versions of the above information to make code run faster -- relies
  68. * on fact that TYPE_i == i.
  69. */

  70. #define                MAX_TYPES        5                /* max number of types above */

  71. static struct _randomjunk {
  72.         int        degrees[MAX_TYPES];
  73.         int        seps[MAX_TYPES];
  74.         long        randtbl[ DEG_3 + 1 ];
  75. /*
  76. * fptr and rptr are two pointers into the state info, a front and a rear
  77. * pointer.  These two pointers are always rand_sep places aparts, as they cycle
  78. * cyclically through the state information.  (Yes, this does mean we could get
  79. * away with just one pointer, but the code for random() is more efficient this
  80. * way).  The pointers are left positioned as they would be from the call
  81. *                        initstate(1, randtbl, 128)
  82. * (The position of the rear pointer, rptr, is really 0 (as explained above
  83. * in the initialization of randtbl) because the state table pointer is set
  84. * to point to randtbl[1] (as explained below).
  85. */
  86.         long        *fptr, *rptr;
  87. /*
  88. * The following things are the pointer to the state information table,
  89. * the type of the current generator, the degree of the current polynomial
  90. * being used, and the separation between the two pointers.
  91. * Note that for efficiency of random(), we remember the first location of
  92. * the state information, not the zeroeth.  Hence it is valid to access
  93. * state[-1], which is used to store the type of the R.N.G.
  94. * Also, we remember the last location, since this is more efficient than
  95. * indexing every time to find the address of the last element to see if
  96. * the front and rear pointers have wrapped.
  97. */
  98.         long        *state;
  99.         int        rand_type, rand_deg, rand_sep;
  100.         long        *end_ptr;
  101. } *__randomjunk, *_randomjunk(void), _randominit = {
  102.         /*
  103.          * Initially, everything is set up as if from :
  104.          *                initstate(1, &randtbl, 128);
  105.          * Note that this initialization takes advantage of the fact
  106.          * that srandom() advances the front and rear pointers 10*rand_deg
  107.          * times, and hence the rear pointer which starts at 0 will also
  108.          * end up at zero; thus the zeroeth element of the state
  109.          * information, which contains info about the current
  110.          * position of the rear pointer is just
  111.          *        MAX_TYPES*(rptr - state) + TYPE_3 == TYPE_3.
  112.          */
  113.         { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 },
  114.         { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 },
  115.         { TYPE_3,
  116.         (long)0x9a319039, (long)0x32d9c024, (long)0x9b663182, (long)0x5da1f342,
  117.         (long)0xde3b81e0, (long)0xdf0a6fb5, (long)0xf103bc02, (long)0x48f340fb,
  118.         (long)0x7449e56b, (long)0xbeb1dbb0, (long)0xab5c5918, (long)0x946554fd,
  119.         (long)0x8c2e680f, (long)0xeb3d799f, (long)0xb11ee0b7, (long)0x2d436b86,
  120.         (long)0xda672e2a, (long)0x1588ca88, (long)0xe369735d, (long)0x904f35f7,
  121.         (long)0xd7158fd6, (long)0x6fa6f051, (long)0x616e6b96, (long)0xac94efdc,
  122.         (long)0x36413f93, (long)0xc622c298, (long)0xf5a42ab8, (long)0x8a88d77b,
  123.         (long)0xf5ad9d0e, (long)0x8999220b, (long)0x27fb47b9 },
  124.         &_randominit.randtbl[ SEP_3 + 1 ],
  125.         &_randominit.randtbl[1],
  126.         &_randominit.randtbl[1],
  127.         TYPE_3, DEG_3, SEP_3,
  128.         &_randominit.randtbl[ DEG_3 + 1]
  129. };

  130. long random(void);

  131. static struct _randomjunk *
  132. _randomjunk(void)
  133. {
  134.         struct _randomjunk *rp = __randomjunk;

  135.         if (rp == 0) {
  136.                 rp = (struct _randomjunk *)malloc(sizeof (*rp));
  137.                 if (rp == 0)
  138.                         return (0);
  139.                 *rp = _randominit;
  140.                 __randomjunk = rp;
  141.         }
  142.         return (rp);
  143. }

  144. /*
  145. * srandom:
  146. * Initialize the random number generator based on the given seed.  If the
  147. * type is the trivial no-state-information type, just remember the seed.
  148. * Otherwise, initializes state[] based on the given "seed" via a linear
  149. * congruential generator.  Then, the pointers are set to known locations
  150. * that are exactly rand_sep places apart.  Lastly, it cycles the state
  151. * information a given number of times to get rid of any initial dependencies
  152. * introduced by the L.C.R.N.G.
  153. * Note that the initialization of randtbl[] for default usage relies on
  154. * values produced by this routine.
  155. */

  156. void
  157. srandom(unsigned x)
  158. {
  159.         struct _randomjunk *rp = _randomjunk();
  160.         int                i;

  161.         if (rp == 0)
  162.                 return;
  163.         if (rp->rand_type  ==  TYPE_0)  {
  164.             rp->state[0] = x;
  165.         } else  {
  166.             rp->state[0] = x;
  167.             for (i = 1; i < rp->rand_deg; i++)  {
  168.                 rp->state[i] = 1103515245*rp->state[i - 1] + 12345;
  169.             }
  170.             rp->fptr = &rp->state[rp->rand_sep];
  171.             rp->rptr = &rp->state[0];
  172.             for (i = 0; i < 10 * rp->rand_deg; i++)
  173.                 random();
  174.         }
  175. }



  176. /*
  177. * initstate:
  178. * Initialize the state information in the given array of n bytes for
  179. * future random number generation.  Based on the number of bytes we
  180. * are given, and the break values for the different R.N.G.'s, we choose
  181. * the best (largest) one we can and set things up for it.  srandom() is
  182. * then called to initialize the state information.
  183. * Note that on return from srandom(), we set state[-1] to be the type
  184. * multiplexed with the current value of the rear pointer; this is so
  185. * successive calls to initstate() won't lose this information and will
  186. * be able to restart with setstate().
  187. * Note: the first thing we do is save the current state, if any, just like
  188. * setstate() so that it doesn't matter when initstate is called.
  189. * Returns a pointer to the old state.
  190. *
  191. * Arguments:
  192. *        seed:                seed for R. N. G.
  193. *        arg_state:        pointer to state array
  194. *        n:                # bytes of state info
  195. */

  196. char  *
  197. initstate(unsigned seed, char *arg_state, int n)
  198. {
  199.         struct _randomjunk *rp = _randomjunk();
  200.         char                *ostate;

  201.         if (rp == 0)
  202.                 return (0);
  203.         ostate = (char *)(&rp->state[-1]);

  204.         if (rp->rand_type  ==  TYPE_0)  rp->state[-1] = rp->rand_type;
  205.         else  rp->state[-1] =
  206.             MAX_TYPES*(rp->rptr - rp->state) + rp->rand_type;
  207.         if (n < BREAK_0) {
  208.                 fprintf(stderr,
  209.         "initstate: state array too small, ignored; minimum size is %d bytes\n",
  210.                         BREAK_0);
  211.                 return (0);
  212.         } else if (n < BREAK_1) {
  213.                 rp->rand_type = TYPE_0;
  214.                 rp->rand_deg = DEG_0;
  215.                 rp->rand_sep = SEP_0;
  216.         } else if (n < BREAK_2) {
  217.                 rp->rand_type = TYPE_1;
  218.                 rp->rand_deg = DEG_1;
  219.                 rp->rand_sep = SEP_1;
  220.         } else if (n < BREAK_3) {
  221.                 rp->rand_type = TYPE_2;
  222.                 rp->rand_deg = DEG_2;
  223.                 rp->rand_sep = SEP_2;
  224.         } else if (n < BREAK_4) {
  225.                 rp->rand_type = TYPE_3;
  226.                 rp->rand_deg = DEG_3;
  227.                 rp->rand_sep = SEP_3;
  228.         } else  {
  229.                 rp->rand_type = TYPE_4;
  230.                 rp->rand_deg = DEG_4;
  231.                 rp->rand_sep = SEP_4;
  232.         }
  233.         rp->state = &((long *)arg_state)[1];        /* first location */
  234.         rp->end_ptr = &rp->state[rp->rand_deg];        /* set end_ptr before srandom */
  235.         srandom(seed);
  236.         rp->state[-1] = (rp->rand_type == TYPE_0) ? rp->rand_type
  237.                         : MAX_TYPES * (rp->rptr - rp->state) + rp->rand_type;
  238.         return (ostate);
  239. }


  240. /*
  241. * setstate:
  242. * Restore the state from the given state array.
  243. * Note: it is important that we also remember the locations of the pointers
  244. * in the current state information, and restore the locations of the pointers
  245. * from the old state information.  This is done by multiplexing the pointer
  246. * location into the zeroeth word of the state information.
  247. * Note that due to the order in which things are done, it is OK to call
  248. * setstate() with the same state as the current state.
  249. * Returns a pointer to the old state information.
  250. */

  251. char  *
  252. setstate(char *arg_state)
  253. {
  254.         struct _randomjunk *rp = _randomjunk();
  255.         long                *new_state;
  256.         int                type;
  257.         int                rear;
  258.         char                        *ostate;

  259.         if (rp == 0)
  260.                 return (0);
  261.         new_state = (long *)arg_state;
  262.         type = new_state[0] % MAX_TYPES;
  263.         rear = new_state[0] / MAX_TYPES;
  264.         ostate = (char *)(&rp->state[-1]);

  265.         rp->state[-1] = (rp->rand_type == TYPE_0) ? rp->rand_type
  266.                         : MAX_TYPES*(rp->rptr - rp->state) + rp->rand_type;
  267.         switch (type)  {
  268.         case  TYPE_0:
  269.         case  TYPE_1:
  270.         case  TYPE_2:
  271.         case  TYPE_3:
  272.         case  TYPE_4:
  273.                 rp->rand_type = type;
  274.                 rp->rand_deg = rp->degrees[type];
  275.                 rp->rand_sep = rp->seps[type];
  276.                 break;

  277.         default:
  278.                 fprintf(stderr, "setstate: invalid state info; not changed.\n");
  279.         }
  280.         rp->state = &new_state[1];
  281.         if (rp->rand_type != TYPE_0)  {
  282.             rp->rptr = &rp->state[rear];
  283.             rp->fptr = &rp->state[(rear + rp->rand_sep) % rp->rand_deg];
  284.         }
  285.         rp->end_ptr = &rp->state[rp->rand_deg];        /* set end_ptr too */
  286.         return (ostate);
  287. }


  288. /*
  289. * random:
  290. * If we are using the trivial TYPE_0 R.N.G., just do the old linear
  291. * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
  292. * same in all ther other cases due to all the global variables that have been
  293. * set up.  The basic operation is to add the number at the rear pointer into
  294. * the one at the front pointer.  Then both pointers are advanced to the next
  295. * location cyclically in the table.  The value returned is the sum generated,
  296. * reduced to 31 bits by throwing away the "least random" low bit.
  297. * Note: the code takes advantage of the fact that both the front and
  298. * rear pointers can't wrap on the same call by not testing the rear
  299. * pointer if the front one has wrapped.
  300. * Returns a 31-bit random number.
  301. */

  302. long
  303. random(void)
  304. {
  305.         struct _randomjunk *rp = _randomjunk();
  306.         long                i;

  307.         if (rp == 0)
  308.                 return (0);
  309.         if (rp->rand_type  ==  TYPE_0)  {
  310.             i = rp->state[0] = (rp->state[0]*1103515245 + 12345)&0x7fffffff;
  311.         } else  {
  312.             *rp->fptr += *rp->rptr;
  313.             i = (*rp->fptr >> 1)&0x7fffffff;        /* chucking least random bit */
  314.             if (++rp->fptr  >=  rp->end_ptr)  {
  315.                 rp->fptr = rp->state;
  316.                 ++rp->rptr;
  317.             } else if (++rp->rptr  >=  rp->end_ptr)
  318.                 rp->rptr = rp->state;
  319.         }
  320.         return (i);
  321. }


复制代码

论坛徽章:
0
4 [报告]
发表于 2006-03-29 20:29 |只看该作者
非常感谢,(太长了)收藏起来慢慢研究

论坛徽章:
0
5 [报告]
发表于 2006-03-29 21:28 |只看该作者

回复 3楼 westgarden 的帖子

太崇拜了!!!向你致敬

论坛徽章:
0
6 [报告]
发表于 2006-03-30 00:12 |只看该作者
开源的好处!

上面的random代码是Solaris 10上的。

还有,学习系统编程推荐用Solaris(纯属给Sun microsystems做广告)。
因为:
1)免费的UNIX
2)开放源代码
3)Solaris对POSIX的支持非常好。


[ 本帖最后由 westgarden 于 2006-3-30 00:14 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2006-03-30 13:56 |只看该作者
以前写仿真程序用到的产生随机数的,可以参考一下.
其中rand_num函数中的from和to分别定义了你想产生随机数的范围.

int number_mm( void )
{
    int *piState;
    int iState1;
    int iState2;
    int iRand;
    piState = &rgi_state[2];
    iState1 = piState[-2];
    iState2 = piState[-1];
    iRand = ( piState[iState1] + piState[iState2] )& ( ( 1 << 30 ) - 1 );
    piState[iState1] = iRand;
    if ( ++iState1 == 55 )
            iState1 = 0;
    if ( ++iState2 == 55 )
            iState2 = 0;
    piState[-2] = iState1;
    piState[-1] = iState2;
    return iRand >> 6;
}

/*
* Generate a random number.
* the range of generated random number can be defined between 'from' and 'to'
*/
int rand_num( int from, int to )
{
    int power;
    int number;
    if ( ( to = to - from + 1 ) <= 1 )
            return from;
    for ( power = 2; power < to; power <<= 1 )
            ;
    while ( ( number = number_mm( ) & ( power - 1 ) ) >= to )
            ;
    return from + number;
}

/*
* this is the Mitchell-Moore algorithm from Knuth, Volume II, the Art of Computer Programming
*/
void init_rand_seed( )
{
    int *piState;
    int iState;
    piState = &rgi_state[2];
    piState[-2] = 55 - 55;
    piState[-1] = 55 - 24;
    piState[0] = ( (int) time( NULL ) ) & ( ( 1 << 30 ) - 1 );
    piState[1] = 1;
    for ( iState = 2; iState < 55; iState++ )
        {
                piState[iState] = ( piState[iState-1] + piState[iState-2] )& ( ( 1 << 30 ) - 1 );
        }

    return;
}

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2006-03-30 14:44 |只看该作者
RH8 是哪年哪月的东西,早就过时了。

论坛徽章:
0
9 [报告]
发表于 2006-03-30 15:47 |只看该作者
linux可以读/dev/random设备文件。
FYI:man 4 random

论坛徽章:
0
10 [报告]
发表于 2006-03-30 23:00 |只看该作者
太棒了,谢谢各位
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP