模仿Python`随机。随机()`C中的功能

2024-10-02 00:21:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用C语言创建Python中使用的mersennetwister(MT)。在

基于Lib/random.py以及读取the docs,整个机器翻译似乎是在{}中实现的,它是用C实现的:

The underlying implementation in C is both fast and threadsafe.

通过google搜索“Python随机”,我找到了this page on GitHub,它似乎正是我要找的,尽管它似乎不是官方的。在

我使用了源代码,除去了除了MT本身、seed函数和double creation函数之外的所有内容。我还更改了一些类型,使整数为32位。在

首先,这里是许可证信息(为了安全起见)

^{pr2}$

这是一个精简的头文件(删除了Python的所有内容)。在

mt.h

#ifndef MT_H
#define MT_H

#include <stdint.h>

#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */

typedef struct {
        uint32_t state[N];
        uint32_t index;
} RandomObject;

static uint32_t
genrand_int32(RandomObject *self)
{
    uint32_t y;
    static uint32_t mag01[2]={0x0UL, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */
    uint32_t *mt;

    mt = self->state;
    if (self->index >= N) { /* generate N words at one time */
        uint32_t kk;

        for (kk=0;kk<N-M;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        for (;kk<N-1;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

        self->index = 0;
    }

    y = mt[self->index++];
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);
    return y;
}

static double 
random_random(RandomObject *self)
{
        uint32_t a=genrand_int32(self)>>5, b=genrand_int32(self)>>6;
        return (double)((a*67108864.0+b)*(1.0/9007199254740992.0));
}

static void
init_genrand(RandomObject *self, uint32_t s)
{
    uint32_t mti;
    uint32_t *mt;

    mt = self->state;
    mt[0]= s & 0xffffffffUL;
    for (mti=1; mti<N; mti++) {
        mt[mti] =
        (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array mt[].                                */
        /* 2002/01/09 modified by Makoto Matsumoto                     */
        mt[mti] &= 0xffffffffUL;
        /* for >32 bit machines */
    }
    self->index = mti;
    return;
}

#endif

这里有一个主函数,它简单地创建一个MT对象,为它种子,然后抛出一个随机的double。在

main.c

#include <stdio.h>
#include "mt.h"

int main() {
    RandomObject rand;
    init_genrand(&rand, 0x1234);
    printf("%lf\n", random_random(&rand));
    return 0;
}

输出是:0.279194。在

其思想是,当我在python中执行等效过程时,我会得到相同的随机数:

Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import random
>>> random.seed(0x1234)
>>> random.random()
0.9281175899596723

当然,输出是不同的(否则我不会在这里询问)。在

我的问题是:我的程序出了什么问题?我只是用错了来源吗?关于Python如何处理C返回的值,我是否做出了错误的假设?在

老实说,我对Python不太了解,所以我可能在某个地方犯了一个愚蠢的错误。在


Tags: theselfforindexmaskrandommtuint32
1条回答
网友
1楼 · 发布于 2024-10-02 00:21:10

您缺少的是,random.seed()没有调用init_genrand()来设定初始状态but use ^{} instead(这是因为在Python中,一个整数可以是任意大小的,我们希望将种子的所有位捕获到该状态中)。在

RandomObject rand;
uint32_t key[] = {0x1234};
init_by_array(&rand, key, sizeof(key)/sizeof(*key));  // < 
printf("%f\n", random_random(&rand));

相关问题 更多 >

    热门问题