C 生成没有时间的随机值
我想在不使用time.h库的情况下重复生成随机数。我看到另一篇关于使用的帖子C 生成没有时间的随机值,c,random,srand,C,Random,Srand,我想在不使用time.h库的情况下重复生成随机数。我看到另一篇关于使用的帖子 srand(getpid()); 然而,这似乎对我不起作用。getpid尚未声明。这是因为我错过了图书馆吗?如果是的话,我需要弄清楚如何在不使用除我目前拥有的库之外的任何其他库的情况下随机生成数字 #include <stdio.h> #include <stdlib.h> int main(void) { int minute, hour, day, month, year;
srand(getpid());
然而,这似乎对我不起作用。getpid尚未声明。这是因为我错过了图书馆吗?如果是的话,我需要弄清楚如何在不使用除我目前拥有的库之外的任何其他库的情况下随机生成数字
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int minute, hour, day, month, year;
srand(getpid());
minute = rand() % (59 + 1 - 0) + 0;
hour = rand() % (23 + 1 - 0) + 0;
day = rand() % (31 + 1 - 1) + 1;
month = rand() % (12 + 1 - 1) + 1;
year = 2018;
printf("Transferred successfully at %02d:%02d on %02d/%02d/%d\n", hour,
minute, day, month, year);
return 0;
}
#包括
#包括
内部主(空){
整数分、时、日、月、年;
srand(getpid());
分钟=兰德()%(59+1-0)+0;
小时=兰德()%(23+1-0)+0;
日=兰德()%(31+1-1)+1;
月份=兰德()%(12+1-1)+1;
年份=2018年;
printf(“在%02d/%02d/%d上的%02d:%02d成功传输”,小时,
分、日、月、年);
返回0;
}
我只能使用库
和
和
——严格的作业指导原则
getpid尚未声明
否,因为您没有在声明它的位置包含
标题(根据您的,您不能使用它,因为您被限制使用
、
和
)
在这种情况下,我会使用
#include <stdlib.h>
#include <stdio.h>
static int randomize_helper(FILE *in)
{
unsigned int seed;
if (!in)
return -1;
if (fread(&seed, sizeof seed, 1, in) == 1) {
fclose(in);
srand(seed);
return 0;
}
fclose(in);
return -1;
}
static int randomize(void)
{
if (!randomize_helper(fopen("/dev/urandom", "r")))
return 0;
if (!randomize_helper(fopen("/dev/arandom", "r")))
return 0;
if (!randomize_helper(fopen("/dev/random", "r")))
return 0;
/* Other randomness sources (binary format)? */
/* No randomness sources found. */
return -1;
}
/dev/urandom
和/dev/random
字符设备在Linux、FreeBSD、macOS、iOS、Solaris、NetBSD、Tru64 Unix 5.1B、AIX 5.2、HP-UX 11i v2和OpenBSD 5.1及更高版本上的/dev/random
和/dev/arandom
中提供
和往常一样,Windows似乎不提供任何此类随机性源:Windows C程序必须使用专有的Microsoft界面
如果输入流为空,或者无法从中读取无符号整数,则随机化\u helper()
将返回非零。如果它可以从中读取一个无符号整数,则它用于为标准伪随机数生成器种子,您可以使用rand()
(该生成器返回介于0和rand\u MAX
之间的int
)。在所有情况下,randomize\u helper()
关闭非空流
您可以简单地将其他二进制随机性源添加到randomize()
如果randomize()
返回0,rand()
应该返回伪随机数。否则,rand()
将返回相同的默认伪随机数序列。(它们仍然是“随机的”,但每次运行程序时都会出现相同的顺序。如果randomize()
返回0,则每次运行程序时的顺序都会不同。)
大多数标准的C
rand()
实现都是线性全等伪随机数生成器,参数的选择往往很差,因此速度慢,不太“随机”
对于非加密工作,我喜欢实现函数家族中的一个,最初由George Marsaglia编写。它们非常、非常快,而且相当随机;他们通过了大多数统计随机性测试,比如
在OP的情况下,可以使用发电机。根据当前的C标准,unsigned int
至少是32位,因此我们可以将其用作生成器类型。让我们看一下,实现一个替代标准srand()/rand()的方法会是什么样子:
#include <stdlib.h>
#include <stdio.h>
/* The Xorwow PRNG state. This must not be initialized to all zeros. */
static unsigned int prng_state[5] = { 1, 2, 3, 4, 5 };
/* The Xorwow is a 32-bit linear-feedback shift generator. */
#define PRNG_MAX 4294967295u
unsigned int prng(void)
{
unsigned int s, t;
t = prng_state[3] & PRNG_MAX;
t ^= t >> 2;
t ^= t << 1;
prng_state[3] = prng_state[2];
prng_state[2] = prng_state[1];
prng_state[1] = prng_state[0];
s = prng_state[0] & PRNG_MAX;
t ^= s;
t ^= (s << 4) & PRNG_MAX;
prng_state[0] = t;
prng_state[4] = (prng_state[4] + 362437) & PRNG_MAX;
return (t + prng_state[4]) & PRNG_MAX;
}
static int prng_randomize_from(FILE *in)
{
size_t have = 0, n;
unsigned int seed[5] = { 0, 0, 0, 0, 0 };
if (!in)
return -1;
while (have < 5) {
n = fread(seed + have, sizeof seed[0], 5 - have, in);
if (n > 0 && ((seed[0] | seed[1] | seed[2] | seed[3] | seed[4]) & PRNG_MAX) != 0) {
have += n;
} else {
fclose(in);
return -1;
}
}
fclose(in);
prng_seed[0] = seed[0] & PRNG_MAX;
prng_seed[1] = seed[1] & PRNG_MAX;
prng_seed[2] = seed[2] & PRNG_MAX;
prng_seed[3] = seed[3] & PRNG_MAX;
prng_seed[4] = seed[4] & PRNG_MAX;
/* Note: We might wish to "churn" the pseudorandom
number generator state, to call prng()
a few hundred or thousand times. For example:
for (n = 0; n < 1000; n++) prng();
This way, even if the seed has clear structure,
for example only some low bits set, we start
with a PRNG state with set and clear bits well
distributed.
*/
return 0;
}
int prng_randomize(void)
{
if (!prng_randomize_from(fopen("/dev/urandom", "r")))
return 0;
if (!prng_randomize_from(fopen("/dev/arandom", "r")))
return 0;
if (!prng_randomize_from(fopen("/dev/random", "r")))
return 0;
/* Other sources? */
/* No randomness sources found. */
return -1;
}
请注意,PRNG_MAX
具有双重用途。一方面,它告诉prng()
可以返回的最大值——这是一个无符号int,不像rand()
那样的int。另一方面,因为它必须是232-1=4294967295,所以我们也使用它来确保在序列中生成下一个伪随机数时的临时结果保持32位。如果在stdint.h
或inttypes.h
中声明的uint32\t
类型可用,我们可以使用它并删除掩码(&PRNG\u MAX
)
请注意,编写prng\u randomize\u from()
函数时,即使随机性源无法一次提供所有请求的字节,并返回“短计数”,该函数仍能工作。在实践中是否会发生这种情况有待讨论,但我更愿意肯定。还请注意,如果该状态全部为零,则它不接受该状态,因为这是Xorwow PRNG的单个禁止初始种子状态
显然,您可以在同一程序中同时使用srand()
/rand()
和prng()
/prng\u randomize()
。我编写它们是为了让Xorwow生成器函数都以prng开始
通常,我会将PRNG实现放入一个头文件中,这样我就可以通过编写一个小的测试程序来轻松地测试它(验证它是否工作);而且我可以通过切换到另一个头文件来切换PRNG实现。(在某些情况下,我将PRNG状态放入一个结构中,并让调用者提供一个指向该状态的指针,以便任意数量的PRNG可以相互独立地并发使用。)
然而,这似乎对我不起作用。getpid尚未声明
这是因为您需要包含getpid()
的标题:
正如其他答案所指出的,您需要包括
unistd.h
标题。如果您不想这样做,那么将getpid()
的声明放在main()
之上。请阅读此处的getpid()
手册页
一种方法可能是
#include <stdio.h>
#include <stdlib.h>
pid_t getpid(void); /* put the declrataion of getpid(), if don't want to include the header */
int main(void) {
/* .. some code .. */
return 0;
}
我只能在作业中使用库和严格的指导原则。@AngusRyan:那么你就不能使用
getpid()
。你在使用Linux吗?如果是这样的话,您可以从/dev/uradom
中为内置PRNG添加种子。请注意,它是非常特定于Linux的,尽管.BSD(macOS和MacOSX)既有/dev/random
又有/dev/urandom
,后者记录为:/dev/urandom
是Linux的兼容性节点。在Linux上,如果熵池耗尽,/dev/urandom
将产生较低质量的输出,而/dev/random
将更喜欢阻塞并等待额外的e
int main(void)
{
int i;
if (prng_randomize())
fprintf(stderr, "Warning: No randomness sources found!\n");
for (i = 0; i < 10; i++)
printf("%u\n", prng());
return EXIT_SUCCESS;
}
#include <sys/types.h>
#include <unistd.h>
srand((unsigned int)time(NULL));
#include <stdio.h>
#include <stdlib.h>
pid_t getpid(void); /* put the declrataion of getpid(), if don't want to include the header */
int main(void) {
/* .. some code .. */
return 0;
}
srand((unsigned int)time(NULL));