Cython随机滚动不会产生预期的输出

时间:2014-06-24 08:30:07

标签: python random cython

我正在关注Hans Petter Langtangen的tutorial,以便更快地了解Cython,以便快速生成随机数。

作者有以下一行:

r = 1 + int(rand()/(RAND_MAX*6.0))

在他的教程中声称产生1到6之间的随机整数。对我来说,它看起来像是一个错误,因为rand()(从libc.stdlib cimported)从0生成一个随机整数到RAND_MAX,所以我猜行

r = 1 + int(6*rand()/(RAND_MAX(1.0))

应该更适合那里。所以我创建了一个小的Cython脚本,它应该在1和n之间滚动一个随机整数,同时打印调试消息。这是脚本:

    from libc.stdlib cimport rand, RAND_MAX

    def print_rand(int n):
        cdef int r
        print "max", RAND_MAX
        cdef int roll
        roll = rand()
        print "roll", roll
        r = 1 + int(n*roll/(RAND_MAX*1.0))
        print r

然后我使用以下setup.py脚本编译了脚本:

    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext

    setup(name='Random print',
          ext_modules=[Extension('_rand', ['rand.pyx'],)],
          cmdclass={'build_ext': build_ext},)

通过

运行它
python setup.py build_ext --inplace

为了测试,我打开了IPython,发生了以下谜团:

In [1]: import _rand

In [2]: _rand.print_rand(1000)
max 2147483647
roll 1804289383
1

但这没有意义,因为

In [3]: 1 + int(1000*1804289383/(2147483647*1.0))
Out[3]: 841

我在这里缺少什么?

1 个答案:

答案 0 :(得分:3)

乘法

n*roll

的结果太大,无法容纳Cython int。与Python ints不同,它会在发生这种情况时自动切换到任意精度表示,Cython会像C一样处理溢出。这通常意味着丢弃不适合的高位;我不确定它是否是Cython中的未定义行为(在这种情况下会发生更糟糕的事情),或者Cython是否保证特定的溢出处理。