C 语言 rand 和 srand 使用方法

前言

有时我们想用 rand() 生成一组随机数,虽然我们调用了 srand(),但是生成的值还是一样。为什么会产生这种情况?又该如何解决?下面将用第一视角一起探究这其中的奥秘。

随机

问题出现

场景描述

想生成一组整形随机数,放入数组中,用来测试自己的排序是否正确。于是我写出了下面的代码,用来生成随机数。

先简单了解下用到的函数

// 成功时返回编码成 time_t 对象的当前日历时间
time_t time(time_t* timer);

// 以值 seed 播种 rand() 所用的随机数生成器
// 通常来说,应该只播种一次随机数生成器
// 在程序开始处,任何到 rand() 的调用前
void srand(unsigned seed);

// 产生一个伪随机数
// 返回 0 与 RAND_MAX 间的随机整数值
int rand(void);
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
  int arr[10] = {0};
  
  for (int i = 0; i < 10; ++i) {
    srand((unsigned)time(NULL));
    // 两个相减是为了出现负的随机数,使测试范围更广
    arr[i] = (rand() % 100 + 1) - (rand() % 100 + 1);
    printf("%d ", arr[i]);
  }
  return 0;
}

我发现尽管我调用了 srand(),可生成的数组值还是同一个。

我思考后想到,因为 for 循环执行速度太快,整个程序都是在一秒内完成的。所以出现了都是同一个值的情况。

初步解决

于是我想出了下面的解决方法

我可以在 for 循环内调用 sleep(),让我的电脑休眠一下,这样就不会出现上述情况了。

于是我写出了下方的代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

int main() {
  int arr[10] = {0};

  for (int i = 0; i < 10; ++i) {
    sleep(1);
    srand((unsigned)time(NULL));
    arr[i] = (rand() % 100 + 1) - (rand() % 100 + 1);
    printf("%d\n", arr[i]);
  }
  return 0;
}

通过休眠后,就成功解决问题了。

可是,如果睡眠时间太短,那么还是会出现重复的现象;如果睡眠时间太长,程序运行速度就太慢。

最终方法

因为上述的原因,我继续查询资料,了解了 rand()srand() 的原理,成功解决了该问题。

srand() 传入一个数值后,srand() 会根据这个值生成一个随机序列表(通常有 4,294,967,296 个数),传入相同的数生成的序列表是相同的。然后 rand() 从序列的头部取出一个数返回,并将这个数放在随机序列表尾部

此时,上面出现的问题也很好解决了。因为计算机运行速度很快,所以我们每次进入循环都会生成一个相同的随机序列表,rand() 只会取出其第一个数。

要解决这个问题,我们只 需要在循环前调用一次 srand() 就好了,这样就不会重复生成序列表了。

下方是最终的代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
  int arr[10] = {0};
  srand((unsigned int)time(NULL));
  
  for (int i = 0; i < 10; ++i) {
    arr[i] = (rand() % 100 + 1) - (rand() % 100 + 1);
    printf("%d ", arr[i]);
  }
  return 0;
}
  • 58
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值