如何在C中生成随机int?
是否有在C中生成随机int数的函数? 或者我必须使用第三方库吗?
#1楼
让我们来看看。 首先,我们使用srand()函数为随机化器播种。 基本上,计算机可以根据提供给srand()的数字生成随机数。 如果给出相同的种子值,则每次都会生成相同的随机数。
因此,我们必须使用始终在变化的值为随机化器播种。 我们通过使用time()函数向其提供当前时间的值来实现此目的。
现在,当我们调用rand()时,每次都会产生一个新的随机数。
#include <stdio.h>int random_number(int min_num, int max_num);int main(void)
{printf("Min : 1 Max : 40 %d\n", random_number(1,40));printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));return 0;
}int random_number(int min_num, int max_num)
{int result = 0, low_num = 0, hi_num = 0;if (min_num < max_num){low_num = min_num;hi_num = max_num + 1; // include max_num in output} else {low_num = max_num + 1; // include max_num in outputhi_num = min_num;}srand(time(NULL));result = (rand() % (hi_num - low_num)) + low_num;return result;
}
#2楼
试试这个,我把它从上面提到的一些概念中加入:
/*
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.*/int random(int max) {srand((unsigned) time(NULL));return (rand() % max) + 1;
}
#3楼
rand()
是生成随机数的最方便的方法。
您也可以通过random.org等在线服务获取随机数。
#4楼
#include <stdio.h>
#include <dos.h>int random(int range);int main(void)
{printf("%d", random(10));return 0;
}int random(int range)
{struct time t;int r;gettime(&t);r = t.ti_sec % range;return r;
}
#5楼
这是在您选择的两个数字之间获取随机数的好方法。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define randnum(min, max) \((rand() % (int)(((max) + 1) - (min))) + (min))int main()
{srand(time(NULL));printf("%d\n", randnum(1, 70));
}
第一次输出:39
第二次输出:61
输出第三次:65
您可以将randnum
之后的值更改为您选择的任何数字,并在这两个数字之间为您生成一个随机数。
#6楼
听到一个很好的解释为什么使用rand()
在给定范围内产生均匀分布的随机数是一个坏主意,我决定看看输出实际上是多么倾斜。 我的测试案例是公平骰子投掷。 这是C代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main(int argc, char *argv[])
{int i;int dice[6];for (i = 0; i < 6; i++) dice[i] = 0;srand(time(NULL));const int TOTAL = 10000000;for (i = 0; i < TOTAL; i++)dice[(rand() % 6)] += 1;double pers = 0.0, tpers = 0.0;for (i = 0; i < 6; i++) {pers = (dice[i] * 100.0) / TOTAL;printf("\t%1d %5.2f%%\n", dice[i], pers);tpers += pers;}printf("\ttotal: %6.2f%%\n", tpers);
}
这是它的输出:
$ gcc -o t3 t3.c$ ./t3 1666598 16.67% 1668630 16.69%1667682 16.68%1666049 16.66%1665948 16.66%1665093 16.65%total: 100.00%$ ./t3 1667634 16.68%1665914 16.66%1665542 16.66%1667828 16.68%1663649 16.64%1669433 16.69%total: 100.00%
我不知道你需要你的随机数是多么统一,但上面看起来足够均匀以满足大多数需求。
编辑:用比time(NULL)
更好的东西初始化PRNG是个好主意。
#7楼
#include <stdio.h>
#include <stdlib.h>void main()
{int visited[100];int randValue, a, b, vindex = 0;randValue = (rand() % 100) + 1;while (vindex < 100) {for (b = 0; b < vindex; b++) {if (visited[b] == randValue) {randValue = (rand() % 100) + 1;b = 0;}}visited[vindex++] = randValue;}for (a = 0; a < 100; a++)printf("%d ", visited[a]);
}
#8楼
标准C函数是rand()
。 这对于单人纸牌来说已经足够好了,但这太可怕了。 rand()
许多实现循环通过一个简短的数字列表,而低位的循环更短。 一些程序调用rand()
方式很糟糕,计算好的种子传递给srand()
很难。
在C中生成随机数的最佳方法是使用OpenSSL之类的第三方库。 例如,
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {union {unsigned int i;unsigned char c[sizeof(unsigned int)];} u;do {if (!RAND_bytes(u.c, sizeof(u.c))) {fprintf(stderr, "Can't get random bytes!\n");exit(1);}} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */return u.i % limit;
}/* Random double in [0.0, 1.0) */
double random_double() {union {uint64_t i;unsigned char c[sizeof(uint64_t)];} u;if (!RAND_bytes(u.c, sizeof(u.c))) {fprintf(stderr, "Can't get random bytes!\n");exit(1);}/* 53 bits / 2**53 */return (u.i >> 11) * (1.0/9007199254740992.0);
}int main() {printf("Dice: %d\n", (int)(random_uint(6) + 1));printf("Double: %f\n", random_double());return 0;
}
为什么这么多代码? Java和Ruby等其他语言具有随机整数或浮点数的函数。 OpenSSL只提供随机字节,因此我尝试模仿Java或Ruby如何将它们转换为整数或浮点数。
对于整数,我们希望避免模偏差 。 假设我们从rand() % 10000
获得了一些随机的4位整数,但是rand()
只能返回0到32767(就像在Microsoft Windows中一样)。 0到2767之间的每个数字看起来都比2768到9999中的每个数字更频繁。要消除偏差,我们可以在值低于2768时重试rand()
,因为从2768到32767的30000值均匀地映射到10000个值从0到9999。
对于浮点数,我们需要53个随机位,因为double
保持53位精度(假设它是IEEE的两倍)。 如果我们使用超过53位,我们会得到舍入偏差。 一些程序员编写像rand() / (double)RAND_MAX
这样的代码,但rand()
可能只返回31位,或者只返回Windows中的15位。
OpenSSL的RAND_bytes()
可以通过在Linux中读取/dev/urandom
来实现种子本身。 如果我们需要很多随机数,那么从/dev/urandom
读取它们的速度太慢,因为它们必须从内核中复制。 允许OpenSSL从种子生成更多随机数更快。
更多关于随机数字:
- Perl的Perl_seed()是如何在C中为
srand()
计算种子的示例。 它混合来自当前时间,进程ID和一些指针的位,如果它不能读取/dev/urandom
。 - OpenBSD的arc4random_uniform()解释了模偏差。
- java.util.Random的Java API描述了用于从随机整数中去除偏差并将53位打包成随机浮点数的算法。
#9楼
如果您的系统支持arc4random
系列函数,我建议使用它们而不是标准rand
函数。
arc4random
系列包括:
uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)
arc4random
返回一个随机的32位无符号整数。
arc4random_buf
将随机内容放入其参数buf : void *
。 内容量由bytes : size_t
参数确定。
arc4random_uniform
返回一个随机的32位无符号整数,该整数遵循以下规则: 0 <= arc4random_uniform(limit) < limit
,其中limit也是无符号的32位整数。
arc4random_stir
从/dev/urandom
读取数据并将数据传递给arc4random_addrandom
以额外随机化它的内部随机数池。
arc4random_addrandom
由arc4random_stir
用于根据传递给它的数据填充它的内部随机数池。
如果您没有这些功能,但是您使用的是Unix,则可以使用以下代码:
/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */int urandom_fd = -2;void urandom_init() {urandom_fd = open("/dev/urandom", O_RDONLY);if (urandom_fd == -1) {int errsv = urandom_fd;printf("Error opening [/dev/urandom]: %i\n", errsv);exit(1);}
}unsigned long urandom() {unsigned long buf_impl;unsigned long *buf = &buf_impl;if (urandom_fd == -2) {urandom_init();}/* Read 4 bytes, or 32 bits into *buf, which points to buf_impl */read(urandom_fd, buf, sizeof(long));return buf_impl;
}
urandom_init
函数打开/dev/urandom
设备,并将文件描述符放在urandom_fd
。
urandom
函数基本上与对rand
的调用相同,除了更安全,它返回一个long
(容易更改)。
但是, /dev/urandom
可能有点慢,因此建议您将其用作不同随机数生成器的种子。
如果您的系统没有/dev/urandom
,但确实有/dev/random
或类似的文件,那么您只需在urandom_init
更改传递给open
的路径。 urandom_init
和urandom
中使用的调用和API(我相信)符合POSIX标准,因此,应该适用于大多数(如果不是全部)POSIX兼容系统。
注意:如果可用的熵不足,则/dev/urandom
读取将不会阻塞,因此在这种情况下生成的值可能是加密不安全的。 如果您对此感到担心,请使用/dev/random
,如果熵不足,将始终阻止。
如果您在另一个系统(即Windows)上,则使用rand
或某些内部Windows特定于平台的非可移植API。
urandom
, rand
或arc4random
调用的包装函数:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */int myRandom(int bottom, int top){return (RAND_IMPL() % (top - bottom)) + bottom;
}
#10楼
希望比使用srand(time(NULL))
更随机。
#include <time.h>
#include <stdio.h>
#include <stdlib.h>int main(int argc, char **argv)
{srand((unsigned int)**main + (unsigned int)&argc + (unsigned int)time(NULL));srand(rand());for (int i = 0; i < 10; i++)printf("%d\n", rand());
}
#11楼
我的简约解决方案适用于范围[min, max)
随机数。 在调用函数之前使用srand(time(NULL))
。
int range_rand(int min_num, int max_num) {if (min_num >= max_num) {fprintf(stderr, "min_num is greater or equal than max_num!\n"); }return min_num + (rand() % (max_num - min_num));
}
#12楼
如果您需要安全的随机字符或整数:
如何在各种编程语言中安全地生成随机数 ,您需要执行以下操作之一:
- 使用libsodium的
randombytes
API - 非常仔细地从libsodium的sysrandom实现中重新实现你需要的东西
- 更广泛地说, 使用
/dev/urandom
,而不是/dev/random
。 不是OpenSSL(或其他用户空间PRNG)。
例如:
#include "sodium.h"int foo()
{char myString[32];uint32_t myInt;if (sodium_init() < 0) {/* panic! the library couldn't be initialized, it is not safe to use */return 1; }/* myString will be an array of 32 random bytes, not null-terminated */ randombytes_buf(myString, 32);/* myInt will be a random number between 0 and 9 */myInt = randombytes_uniform(10);
}
randombytes_uniform()
是加密安全且无偏的。
#13楼
我在最近的应用程序中遇到了一个严重的伪随机数生成器问题:我通过pyhton脚本重复调用我的C程序,我使用以下代码作为种子:
srand(time(NULL))
但是,因为:
- rand将生成相同的伪随机序列,在srand中给出相同的种子(参见
man srand
); - 如前所述,时间函数仅从第二个时间开始变化:如果您的应用程序在同一秒内多次运行,则
time
将每次返回相同的值。
我的程序生成了相同的数字序列。 你可以做3件事来解决这个问题:
混合时间输出与运行时更改的其他信息(在我的应用程序中,输出名称):
srand(time(NULL) | getHashOfString(outputName))
我使用djb2作为我的哈希函数。
增加时间分辨率。 在我的平台上,
clock_gettime
可用,所以我使用它:#include<time.h> struct timespec nanos; clock_gettime(CLOCK_MONOTONIC, &nanos) srand(nanos.tv_nsec);
一起使用两种方法:
#include<time.h> struct timespec nanos; clock_gettime(CLOCK_MONOTONIC, &nanos) srand(nanos.tv_nsec | getHashOfString(outputName));
选项3确保您(据我所知)最佳种子随机性,但它可能仅在非常快的应用程序上产生差异。 在我看来,选项2是一个安全的赌注。
#14楼
C程序生成9到50之间的随机数
#include <time.h>
#include <stdlib.h>int main()
{srand(time(NULL));int lowerLimit = 10, upperLimit = 50;int r = lowerLimit + rand() % (upperLimit - lowerLimit);printf("%d", r);
}
通常我们可以在lowerLimit和upperLimit-1之间生成一个随机数
即lowerLimit包含或说r∈[lowerLimit,upperLimit)
#15楼
在现代x86_64 CPU上,您可以通过_rdrand64_step()
使用硬件随机数生成器
示例代码:
#include <immintrin.h>uint64_t randVal;
if(!_rdrand64_step(&randVal)) {// Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number
#16楼
尽管所有人都在这里建议rand()
,你不想使用rand()
除非你必须! rand()
产生的随机数通常非常糟糕。 引用Linux手册页:
Linux C库中的
rand()
和srand()
版本使用与randomrandom(3)
和srandom(3)
相同的随机数生成器,因此低阶位应该与高阶位一样随机。 但是,在较旧的rand()实现以及不同系统上的当前实现中, 低阶位比高阶位更不随机 。 当需要良好的随机性时,请勿在可移植的应用程序中使用此功能。 ( 改为使用random(3)
。 )
关于可移植性, random()
也由POSIX标准定义了很长一段时间。 rand()
较旧,它出现在第一个POSIX.1规范(IEEE Std 1003.1-1988)中,而random()
首先出现在POSIX.1-2001(IEEE Std 1003.1-2001)中,但目前的POSIX标准是已经POSIX.1-2008(IEEE Std 1003.1-2008),它在一年前收到了更新(IEEE Std 1003.1-2008,2016版)。 所以我认为random()
非常便携。
POSIX.1-2001还引入了lrand48()
和mrand48()
函数, 请看这里 :
该系列函数应使用线性同余算法和48位整数算法生成伪随机数。
非常好的伪随机源是arc4random()
函数,它在许多系统上都可用。 不是任何官方标准的一部分,在1997年左右出现在BSD中,但你可以在Linux和macOS / iOS等系统上找到它。
#17楼
#include<stdio.h>
#include<stdlib.h>
#include<time.h>//generate number in range [min,max)
int random(int min, int max){int number = min + rand() % (max - min);return number;
}//Driver code
int main(){srand(time(NULL));for(int i = 1; i <= 10; i++){printf("%d\t", random(10, 100));}return 0;
}
#18楼
对于C,STL不存在。你必须random
调用rand
,或者更好。 这些在标准库头文件stdlib.h
中声明。 rand
是POSIX, random
是BSD规范函数。
rand
和random
之间的区别在于random
返回一个更可用的32位随机数, rand
通常返回一个16位数。 BSD联机帮助页显示rand
的低位是循环且可预测的,因此rand
对于小数字可能是无用的。
#19楼
好吧,STL是C ++,而不是C,所以我不知道你想要什么。 但是,如果你想要C,则有rand()
和srand()
函数:
int rand(void);void srand(unsigned seed);
这些都是ANSI C的一部分。还有random()
函数:
long random(void);
但据我所知, random()
不是标准ANSI C.第三方库可能不是一个坏主意,但这完全取决于你真正需要生成的数字的随机性。
#20楼
你想使用rand()
。 注意( 非常重要 ):确保为rand函数设置种子。 如果你不这样做,你的随机数不是真正随机的 。 这非常非常非常重要。 值得庆幸的是,您通常可以使用系统滴答计时器和日期的某种组合来获得良好的种子。
#21楼
<stdlib.h>
的rand()
函数返回0到RAND_MAX
之间的伪随机整数。 您可以使用srand(unsigned int seed)
来设置种子。
通常的做法是将%
运算符与rand()
结合使用以获得不同的范围(但请记住,这会在某种程度上抛弃均匀性)。 例如:
/* random int between 0 and 19 */
int r = rand() % 20;
如果你真的关心一致性,你可以这样做:
/* Returns an integer in the range [0, n).** Uses rand(), and so is affected-by/affects the same seed.*/
int randint(int n) {if ((n - 1) == RAND_MAX) {return rand();} else {// Supporting larger values for n would requires an even more// elaborate implementation that combines multiple calls to rand()assert (n <= RAND_MAX)// Chop off all of the values that would cause skew...int end = RAND_MAX / n; // truncate skewassert (end > 0);end *= n;// ... and ignore results from rand() that fall above that limit.// (Worst case the loop condition should succeed 50% of the time,// so we can expect to bail out of this loop pretty quickly.)int r;while ((r = rand()) >= end);return r % n;}
}
#22楼
FWIW,答案是肯定的,有一个名为rand
的stdlib.h
函数; 此功能主要针对速度和分布进行调整,而不是针对不可预测性。 几乎所有用于各种语言和框架的内置随机函数都默认使用此函数。 还有“加密”随机数生成器,它们的可预测性要低得多,但运行速度要慢得多。 这些应该用于任何类型的安全相关的应用程序。
#23楼
看看ISAAC (间接,移位,累积,添加和计数)。 它均匀分布,平均周期长度为2 ^ 8295。
#24楼
注意 :不要使用
rand()
来保证安全性。 如果您需要加密安全号码, 请参阅此答案 。
#include <time.h>
#include <stdlib.h>srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
编辑 :在Linux上,您可能更喜欢使用random和srandom 。
#25楼
如果您需要比stdlib
提供的质量更好的伪随机数,请查看Mersenne Twister 。 它也更快。 示例实现很多,例如这里 。
如何在C中生成随机int?相关推荐
- integer java 随机_如何在Java中生成随机BigInteger值?
我需要生成0(包含)到n(包含)范围内任意大的随机整数.我最初的想法是调用nextDouble并乘以n,但一旦n大于253,结果将不再是均匀分布的. BigInteger具有以下构造函数: publi ...
- 中boxplot函数的参数设置_如何在Python中生成图形和图表
在本章中,我们将学习如何在Python中生成图形和图表,同时将使用函数和面向对象的方法来可视化数据. Python中常用的一些可视化数据包括以下几种. Matplotlib. Seaborn. ggp ...
- 浅析如何在Nancy中生成API文档
前言 前后端分离,或许是现如今最为流行开发方式,包括UWP.Android和IOS这样的手机客户端都是需要调用后台的API来进行数据的交互. 但是这样对前端开发和APP开发就会面临这样一个问题:如何知 ...
- python实现随机抽取答题_如何在python中实现随机选择
这篇文章主要介绍了如何在python中实现随机选择,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 想从一个序列中随机抽取若干元素,或者想生成几个随机 ...
- 如何在Java中生成比特币钱包地址
让我们通过学习比特币(Bitcoin)如何实施该技术的各个方面来工作,好吗?该技术包括以下几个方面: 比特币地址bitcoin address是用来发送和接收比特币的. 交易transaction是比 ...
- python随机生成英文字母_在Python中生成随机字母
有没有一种方法可以在Python中生成随机字母(如random.randint,但用于字母)? random.randint的范围功能会很好,但是拥有仅输出随机字母的生成器总比没有好. 简单: > ...
- 如何在javascript中生成1到10之间的随机数
在这篇文章中,我们将看到如何在 javascript 中生成 1 到 10 之间的随机数. 如何在javascript中生成1到10之间的随机数 我们可以简单地使用 Math.random() 方法在 ...
- JavaScript 随机数 – 如何在 JS 中生成随机数
在使用 JavaScript 程序时,有时您可能需要生成一个随机数. 例如,您可能希望在开发 JavaScript 游戏(例如猜数字游戏)时生成一个随机数. JavaScript 有许多用于处理数字和 ...
- linux 随机密码更改,如何在Linux中生成EncryptDecrypt随机密码
安全是网络世界中的主要问题之一.网络安全,也称为信息技术安全,重点在于保护计算机,网络,程序和数据免遭意外或未经授权的访问,更改或破坏.我们将密码用于计算机,电子邮件,云,电话,文档等.我们都知道选择 ...
最新文章
- 50本程序员圣经级别书籍!包邮送到家!一书在手,天下我有!
- wxWidgets:wxMemoryDC类用法
- idea maven 出现:Try-with-resources are not supported at language level ‘5‘
- C:03---运算符优先级
- 大小端 Big-Endian 与 Little-Endian
- OLAP系统场景中,GaussDB(for MySQL)借助PQ+NDP让性能提升高达百倍
- 使用Keras框架进行单变量时间序列预测——以上证指数为例
- 爬虫练习五:多进程爬取股市通股票数据
- Node后端数据渲染
- java aes输出长度_关于Java下的AES加密明文长度的问题
- 写入接口c语言_嵌入式LCD的接口类型详解
- 关于:XP精简版装IIS 添加/删除windows组件中找不到IIS
- 俞扬 新书_哇,太好了...新书
- P8-图标字体-font-awesome-伪类-阿里图标字体icnfont-字体-行高-文本样式
- java 10000以内的质数_10000以内有多少质数
- 双系统linux分区扩容,Win7 下Ubuntu14.04 双系统无损扩容
- 关于 Sketch 你可以知道的几个小秘密 (快捷键用法)
- 安装ssd后不识别网卡_安装固态硬盘后读不出来,怎么解决?
- centos7.5安装snipe-it v5.1.2版本开源资产管理软件
- 哪款蓝牙耳机的续航比较好?四款续航时间长的蓝牙耳机测评