64,962
社区成员
srand是指定随机种子,rand生成的是伪随机数。
举个例子,假如有一个uint8的随机种子a初始值为0,uint8的取值范围是0~255,每次rand执行a += 31,超过255就会高位就会溢出
那么多次rand得到的数列就是:
31 62 93 124 155 186 217 248 23 54 85 116 147 178 209 240 15 46 77 108 139 170 201 232 7 38 69 100 131 162 193 224 255 30 61 92 123 154 185 216 247 22 53 84 115 146 177 208 239 14 45 76 107 138 169 200 231 6 37 68 99 130 161 192 223 254 29 60 91 122 153 184 215 246 21 52 83 114 145 176 207 238 13 44 75 106 137 168 199 230 5 36 67 98 129 160 191 222 253 28 59 90 121 152 183 214 245 20 51 82 113 144 175 206 237 12 43 74 105 136 167 198 229 4 35 66 97 128 159 190 221 252 27 58 89 120 151 182 213 244 19 50 81 112 143 174 205 236 11 42 73 104 135 166 197 228 3 34 65 96 127 158 189 220 251 26 57 88 119 150 181 212 243 18 49 80 111 142 173 204 235 10 41 72 103 134 165 196 227 2 33 64 95 126 157 188 219 250 25 56 87 118 149 180 211 242 17 48 79 110 141 172 203 234 9 40 71 102 133 164 195 226 1 32 63 94 125 156 187 218 249 24 55 86 117 148 179 210 241 16 47 78 109 140 171 202 233 8 39 70 101 132 163 194 225 0 31 62 93 124 155 186 217 248 23 54 85 116 147 178 209 240 15 46 77 108 139
可以注意到该数列数值分布看起来是随机的,但是跑了一段之后就会出现重复
31 62 93 124 155 186 217 248 23 54 85 116 147 178 209 240 15 46 77 108 139 170 201 232 7 38 69 100 131 162 193 224 255 30 61 92 123 154 185 216 247 22 53 84 115 146 177 208 239 14 45 76 107 138 169 200 231 6 37 68 99 130 161 192 223 254 29 60 91 122 153 184 215 246 21 52 83 114 145 176 207 238 13 44 75 106 137 168 199 230 5 36 67 98 129 160 191 222 253 28 59 90 121 152 183 214 245 20 51 82 113 144 175 206 237 12 43 74 105 136 167 198 229 4 35 66 97 128 159 190 221 252 27 58 89 120 151 182 213 244 19 50 81 112 143 174 205 236 11 42 73 104 135 166 197 228 3 34 65 96 127 158 189 220 251 26 57 88 119 150 181 212 243 18 49 80 111 142 173 204 235 10 41 72 103 134 165 196 227 2 33 64 95 126 157 188 219 250 25 56 87 118 149 180 211 242 17 48 79 110 141 172 203 234 9 40 71 102 133 164 195 226 1 32 63 94 125 156 187 218 249 24 55 86 117 148 179 210 241 16 47 78 109 140 171 202 233 8 39 70 101 132 163 194 225 0 /* 开始重复 */ 31 62 93 124 155 186 217 248 23 54 85 116 147 178 209 240 15 46 77 108 139
随机数的生成差不多也就是这样的原理,只不过随机数的取值范围更大,算法更复杂一些,出现重复数列的概率更晚一些而已。
srand的作用是指定这个a的初始值,如果你不指定或者指定是固定的数值,那么两次打开进程,出来的随机序列都是一样的,因为起点相同。如果你用当前时间戳值作为随机种子,那么每次打开进程,起点都是不一样的,出来的随机序列也就是向后顺延未知位数的,看起来两次的随机序列并不相同。
srand、rand是否线程安全是实现相关的,标准中没有定义,但是标准中明确说了,第一次调用rand之前如果没有调用过srand,相当于调用srand(1)
不起作用。参考C:\Program Files (x86)\Microsoft SDK\src\crt\rand.c:
/***
*rand.c - random number generator
*
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines rand(), srand() - random number generator
*
*******************************************************************************/
#include <cruntime.h>
#include <mtdll.h>
#include <stddef.h>
#include <stdlib.h>
#ifndef _MT
static long holdrand = 1L;
#endif /* _MT */
/***
*void srand(seed) - seed the random number generator
*
*Purpose:
* Seeds the random number generator with the int given. Adapted from the
* BASIC random number generator.
*
*Entry:
* unsigned seed - seed to seed rand # generator with
*
*Exit:
* None.
*
*Exceptions:
*
*******************************************************************************/
void __cdecl srand (
unsigned int seed
)
{
#ifdef _MT
_getptd()->_holdrand = (unsigned long)seed;
#else /* _MT */
holdrand = (long)seed;
#endif /* _MT */
}
/***
*int rand() - returns a random number
*
*Purpose:
* returns a pseudo-random number 0 through 32767.
*
*Entry:
* None.
*
*Exit:
* Returns a pseudo-random number 0 through 32767.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl rand (
void
)
{
#ifdef _MT
_ptiddata ptd = _getptd();
return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );
#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}
不起作用。证明过程如下:
不设置srand(),子线程rand()都是41.
//test1.c
#include<stdio.h>
#include<pthread.h>
#define NUM_THREADS 5
#include <time.h>
#include <iostream>
using namespace std;
void *PrintTh(void *th){
int i = *((int*)th);
printf("Hello, I'm thread %d, ", i);
printf("%d\n",rand());
return 0;
}
int main(){
int i,ret;
pthread_t p;
for(i=0; i<NUM_THREADS; i++){
printf("create th %d\n",i);
ret = pthread_create(&p,NULL, PrintTh, (void*)&i);
if(ret != 0)
printf("th %d error, code = \n",i);
}
pthread_exit(NULL);
return 0;
}
运行结果:
主线程设置种子为2 srand(2),但子线程依然随机数41。说明子线程没有受到主线程srand的影响。