gpt4 book ai didi

c rand() 函数和 ISAAC 随机数生成器

转载 作者:太空宇宙 更新时间:2023-11-04 08:18:14 26 4
gpt4 key购买 nike

我用 C 编写了一个程序,它使用许多不同的随机数生成器,其中之一是 ISAAC(可在 http://burtleburtle.net/bob/rand/isaacafa.html 获得)。它运行良好,但问题是在 rand.h rand() 中被重新定义为宏。在我的程序中,我也想使用标准的 C rand() 函数。我尝试将宏的名称更改为 rand12(),但我在 ISAAC 中看不到调用宏的任何其他位置,因此这不起作用。

您能否提供一些想法,让我既能保留标准的 rand() 函数又能使用 ISAAC?

最佳答案

鉴于 header rand.h包含:

#ifndef STANDARD
#include "standard.h"
#endif

#ifndef RAND
#define RAND
#define RANDSIZL (8)
#define RANDSIZ (1<<RANDSIZL)

/* context of random number generator */
struct randctx
{
ub4 randcnt;
ub4 randrsl[RANDSIZ];
ub4 randmem[RANDSIZ];
ub4 randa;
ub4 randb;
ub4 randc;
};
typedef struct randctx randctx;

/* If (flag==TRUE), then use the contents of randrsl[0..RANDSIZ-1] as the seed. */
void randinit(/*_ randctx *r, word flag _*/);

void isaac(/*_ randctx *r _*/);

/* Call rand(/o_ randctx *r _o/) to retrieve a single 32-bit random value */
#define rand(r) \
(!(r)->randcnt-- ? \
(isaac(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \
(r)->randrsl[(r)->randcnt])

#endif /* RAND */

您需要对代码做一些工作才能将其与 rand() 一起使用来自 <stdlib.h> . ISAAC 的接口(interface) rand()rand() 的接口(interface)不同来自 <stdlib.h>也是。

为自己创建一个新标题,"isaac.h" ,它定义了处理 ISAAC 系统特性的覆盖函数。

如果您不打算在线程上下文中工作,也许可以

#ifndef ISAAC_H_INCLUDED
#define ISAAC_H_INCLUDED

extern void isaac_init(unsigned long seed);
extern int isaac_rand(void);

#endif

然后您在 isaac.c 中实现这些功能这样他们就可以调用 rand.h 中定义的函数, 和 isaac_rand()包含对 rand() 的调用来自 rand.h 的宏(从某处提供上下文,这是非线程部分的来源)。您可以决定如何处理 seed ,或者是否更改播种机制。

然后您可以使用 isaac_init()isaac_rand()代码中的函数,以及正常的 rand()srand() .

我还会升级 rand.h 中的代码为包中的功能提供完整的原型(prototype)。注释原型(prototype)是它首次编写时的遗留问题,可追溯到 90 年代中期,当时标准 C 编译器还不是普遍可用的。标题中最早的日期是 1996 年;那只是标准 C 编译器几乎普遍可用的风口浪尖。

我注意到标题中的注释(上面已删除)表示代码属于公共(public)领域;这意味着进行您需要的任何修改都是 100% 合法的。


isaac.c

#include "isaac.h"
#include "rand.h"

static randctx control;

void isaac_init(unsigned long seed)
{
assert(seed != 0);
randinit(&control, FALSE);
}

int isaac_rand(void)
{
return rand(&control);
}

此实现会忽略您提供的种子,主要是因为该结构需要八个 32 位数字作为 randrsl 的种子。上下文结构的成员(我称之为 control 的那个)。你可以做一些事情,比如连续 8 次使用种子值而不是完全忽略它,或者每次都给它添加一些数字,或者任何其他更复杂的播种技术。你应该认真看看使用 /dev/urandom作为种子的来源:

#define DEV_URANDOM "/dev/urandom"

int ur = open(DEV_URANDOM, O_RDONLY);
if (ur >= 0)
{
read(ur, control.randrsl, sizeof(control.randrsl));
close(ur);
}

您可以将此代码放入 isaac_init()在调用 randinit() 之前, 你会改变 FALSETRUE .您可能还会丢失 seed isaac_init() 的参数功能。

这给您留下了跟踪随机种子以获得再现性的问题(这在调试时可能很重要)。不过,那是你要解决的问题——有多种方法可以做到这一点。您可能有两个初始化函数:void isaac_init(void)void isaac_rsl(unsigned int *rsl)它需要一个数组 8 unsigned int (或 ub4 )值并将其用作种子而不是 /dev/urandom 的输出.或者你可以传递一个空指针来表示“使用 /dev/urandom 的输出”和一个非空指针来表示“使用我提供的值”。等等

关于c rand() 函数和 ISAAC 随机数生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34571718/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com