主线程中的srand对子线程中的rand函数的种子有起作用吗?

ooolinux 2024-02-21 18:59:47

如题

...全文
218 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 02-21
精选
  • 打赏
  • 举报
回复
您的问题已经帮您同步至问答, 链接: https://ask.csdn.net/questions/8065069, 请您保持关注, 如果回答有帮助解决此问题, 麻烦您动动小手给相关的回答点赞, Ada会在评论区为您更新结题状态
  • 打赏
  • 举报
回复

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的初始值,如果你不指定或者指定是固定的数值,那么两次打开进程,出来的随机序列都是一样的,因为起点相同。如果你用当前时间戳值作为随机种子,那么每次打开进程,起点都是不一样的,出来的随机序列也就是向后顺延未知位数的,看起来两次的随机序列并不相同。

ooolinux 02-22
  • 举报
回复
@火花20180731 明白了
  • 打赏
  • 举报
回复

srand、rand是否线程安全是实现相关的,标准中没有定义,但是标准中明确说了,第一次调用rand之前如果没有调用过srand,相当于调用srand(1)

ooolinux 02-22
  • 举报
回复
@日立奔腾浪潮微软松下联想 我有个CB11.2的FMX程序数字九宫格,32位安卓app运行正常,偶然发现32位win版本exe每次打乱九宫格时(用子线程)都是一样的数字布局,说明win版本子线程的rand没有受到主界面线程srand的影响。
赵4老师 02-22
  • 打赏
  • 举报
回复

不起作用。参考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 */
}



ooolinux 02-22
  • 举报
回复
@赵4老师 多线程的时候, _getptd()-&gt;_holdrand = (unsigned long)seed; 这句怎么理解?
赵4老师 02-23
  • 举报
回复
@ooolinux VS IDE中,在不明白的符号_holdrand上点鼠标右键,在弹出的菜单中选转到定义。
ooolinux 02-23
  • 举报
回复
@赵4老师 应该是每个线程都有独立的_holdrand 作为seed
  • 打赏
  • 举报
回复

不起作用。证明过程如下:

不设置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;
}


运行结果:

img

主线程设置种子为2 srand(2),但子线程依然随机数41。说明子线程没有受到主线程srand的影响。

img

ooolinux 02-22
  • 举报
回复
@太空漫步11 你这个编译器和库(系统)是什么?

64,849

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧