生成随机数 ~详细解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 生成随机数 ~详细解析

如何生成1~100随机数

最近在写一个如何生成随机数的练习:生成一个1~100的随机数,通过百度我发现到是要调用sand函数来实现的,接下来我们慢慢深入了解吧!

得知我们生成随机数要用到sand函数,但我们并不知道这个函数究竟是如何运行的,接下来我们可以在MSDN里查看这个函数的用法。

0a2653c851af460fa595bd959398a8f1.png

通过查看后,得知这个函数会返回一个从0到RAND_MAX的随机整数,对此我并不知道它的数值于是多少,于是我们右键点击转到定义。


#define RAND_MAX 0x7fff

发现define定义的 RAND_MAX大小是0x7fff,转换成十进制也就是32767,也就是说这个函数可以返回一个从0~32767的整型。接下来我们实战一下发现

2d65d23f6d4748949b924e4057485923.png

本以为已经可以生成随机数了,可但是当我第二次运行时发现,它生成的还是这些随机数,也就是说,第一次生成的随机数和第二次生成的是相同的。我这细想肯定出错了,回头看在描述中还有第二句话:在调用rand函数之前,我们要调用srand函数设置生成随机数。对此我又在MSDN中查查srand函数:

6de278e6d6694ce5bb08e7e842b7e74b.png

发现srand函数的参数是一个无符号整型并且无返回值,那我们测试一下,随便给srand输入一个无符号整型比如:100。

8ec4f2997fb246878c34ecd6d122b7c6.png

当再一次运行的时候,程序还是照样生成一样的随机数,只有通过我们改变传入srand的参数时,生成的随机数才会改变。

12c3b7f3f8814309a195c64f051d4445.png

那么问题来了,当我们给srand传入一个随机数,那么rand就会给我们返回一个随机数,想到这里不就出问题了吗?!我们为了生成一个随机数,现在要我们输入一个随机数才行,这不就是先有蛋还是先有鸡的问题嘛!

这时候我们想要给srand传进去一个一直在发生变化的值不就OK了吗?那什么是一直发生变化的呢?我们想到咱电脑上一直在发生变化的~~时间。这时候我们要介绍一个概念:时间戳

时间戳:当前时间相较于计算机起始时间的差值,单位是秒。

34e8d716411043c08c7ffba9fbba23de.png

所以我们用时间戳作为随机数的生成器,那么每一个所生成的随机数都是随机的,所以我们可以给srand传一个时间戳,这时候我们就需要用到time函数,C语言提供的time函数,可以返回一个时间戳。


92ba0822ed0b46e1ae72df8a17d3a45b.png


这里我们可以看到time函数的参数是time_t型指针,返回值是time_t型。通过转到定义发现,是整型和长整型类型,其实time函数最终返回的是一个整数。


d79b274929334152a6d38be91e2d1be3.png


如果创建一个time_t t;即可把t的地址传给参数timer,那么函数就把时间戳的时间放在了t里面,当然这个参数我们也可以不用,于是我们就向time函数传入一个空指针( NULL)即可。当然也可以通过返回值把时间戳返回来,所以我们如果要将time函数的返回值传入srand函数,那么我们就需要将time函数的返回值强制性转化会unsigned int型。


0a2653c851af460fa595bd959398a8f1.png


这样就真正的产生随机数了!但是生成的随机数不在1~100的范围里面。

如何生成规定位数的随机数呢:(1~100)


int ret = rand()%100+1;


可知任何一个数字%100余的数字只能取0~99,我们只需要将所得随机数对100取余数,那么我们得到的数就是0-99的数字,这时再加上1便是1-100的数字了。

同理:要生成三位数:


int ret = rand()%1000+1;


以下是猜数字游戏的全部代码


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
  printf("******1.play*******\n");
  printf("******0.exit*******\n");
  printf("*******************\n");
  printf("*******************\n");
}
void game()
{
  int guess = 0;
  //1.生成一个随机数
  srand((unsigned)time(NULL));
  int ret = rand()%100+1;
  //2.猜数字 
  while (1)
  {
  printf("猜数字:>\n");
     scanf("%d",&guess);
  if (guess < ret)
  {
    printf("猜小了\n");
  }
  else if (guess > ret)
  {
    printf("猜大了\n");
  }
  else
  {
    printf("恭喜你猜对了\n");
    break;
  }
  }
}
int main()
{ 
  int input = 0;
  do
  {
   menu();
   printf("请选择:>");
   scanf("%d",&input);
   switch (input)
   {
   case 1:
    game();
    break;
   case 0:
    printf("退出游戏\n");
    break;
   default:
    printf("选择错误,请重新选择!\n");
    break;
   }
  } while (input);
  return 0;
}


那么到这里就已经讲解完啦,如果文中有错误请指出。


相关文章
|
25天前
|
机器学习/深度学习 算法 安全
随机性、熵与随机数生成器:解析伪随机数生成器(PRNG)和真随机数生成器(TRNG)
随机性在密码学、仿真和机器学习等领域中至关重要,本文探讨了随机性、熵的概念以及伪随机数生成器(PRNG)和真随机数生成器(TRNG)的原理和应用。PRNG通过算法生成看似随机的序列,适用于高效需求;TRNG利用物理过程生成真正随机数,适用于高安全需求。文章还讨论了两者的协同应用及其面临的挑战。
62 5
随机性、熵与随机数生成器:解析伪随机数生成器(PRNG)和真随机数生成器(TRNG)
|
6月前
|
算法 安全 程序员
【C++ 随机数生成器】深入解析C++ 随机数生成器mersenne_twister_engine等
【C++ 随机数生成器】深入解析C++ 随机数生成器mersenne_twister_engine等
241 0
|
JavaScript 前端开发 .NET
|
8天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
28 2
|
1月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
68 0
|
1月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
57 0
|
1月前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
61 0
|
1月前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
83 0
|
8天前
|
存储 安全 Linux
Golang的GMP调度模型与源码解析
【11月更文挑战第11天】GMP 调度模型是 Go 语言运行时系统的核心部分,用于高效管理和调度大量协程(goroutine)。它通过少量的操作系统线程(M)和逻辑处理器(P)来调度大量的轻量级协程(G),从而实现高性能的并发处理。GMP 模型通过本地队列和全局队列来减少锁竞争,提高调度效率。在 Go 源码中,`runtime.h` 文件定义了关键数据结构,`schedule()` 和 `findrunnable()` 函数实现了核心调度逻辑。通过深入研究 GMP 模型,可以更好地理解 Go 语言的并发机制。
|
21天前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
39 3

推荐镜像

更多
下一篇
无影云桌面