【问题标题】:Correct way to generate random numbers in Cython?在 Cython 中生成随机数的正确方法?
【发布时间】:2013-04-14 19:44:27
【问题描述】:

在 Cython 的 [0,1] 中生成随机随机数的最有效和便携的方法是什么?一种方法是使用 C 库中的 INT_MAXrand()

from libc.stdlib cimport rand
cdef extern from "limits.h":
    int INT_MAX
cdef float randnum = rand() / float(INT_MAX)

这样使用INT_MAX可以吗?我注意到它与您从 Python 的 max int 获得的常量完全不同:

import sys
print INT_MAX
print sys.maxint 

产量:

2147483647  (C max int)
9223372036854775807  (python max int)

rand() 的正确“标准化”编号是哪个? 编辑 另外,如果使用从 libc 调用 rand() 的 C 方法,如何设置随机种子(例如基于当前时间播种)?

【问题讨论】:

  • 您是否尝试过获取几千个样本的最大值和最小值,并查看哪个比例因子接近1.0

标签: python random numpy cython


【解决方案1】:

C 标准说 rand 返回一个范围为 0 到 RAND_MAX 的 int,因此将其除以 RAND_MAX(来自 stdlib.h)是对其进行规范化的正确方法。在实践中,RAND_MAX 几乎总是等于 MAX_INT,但不要依赖它。

因为rand 自 C89 以来一直是 ISO C 的一部分,因此保证在任何地方都可用,但不保证其随机数的质量。但是,如果可移植性是您主要关心的问题,那么这是您的最佳选择,除非您愿意使用 Python 的 random 模块。

Python 的sys.maxint 完全是一个不同的概念;它只是 Python 可以在 它自己的 int 类型中表示的最大正数;较大的必须是多头。 Python 的 int 和 long 与 C 没有特别的关系。

【讨论】:

  • 谢谢!你知道如何使用 libc 方法设置种子吗?
  • 我可能会为此使用random.randint(0, INT_MAX),真的。开销不是问题,因为它只会发生一次。
  • 开销是一个主要问题,因为这在需要生成随机数的循环中被多次调用(以便部分地从多项式中采样)。我可以设置 random.randint(0, INT_MAX) 然后调用 C 的 rand() 并让 C 和 Python 种子“同步”吗?
  • 澄清一下:开销只是数字生成的问题,当然正如你所说的那样调用python一次来设置种子根本不是问题
  • 我的意思是使用 random.randint(0, INT_MAX) 作为 libc 的 srand 的参数。
【解决方案2】:

我不确定 drand 是否是新添加的,但它似乎完全符合您的要求,同时避免了代价高昂的分割。

cdef extern from "stdlib.h":
    double drand48()
    void srand48(long int seedval)

cdef extern from "time.h":
    long int time(int)

# srand48(time(0))
srand48(100)
# TODO: this is a seed to reproduce bugs, put to line of code above for
# production
drand48() #This gives a float in range [0,1)

我在研究您的划分方法是否产生足够的随机性时遇到了this idea。我找到的来源很好地说明了在我的情况下,我将随机数与两位数的小数进行比较,所以我真的只需要 3 个小数点的精度。所以 INT_MAX 绰绰有余。但是,drand48 似乎节省了除法成本,因此可能值得使用。

【讨论】:

  • 顺便说一下,这是不可移植的,因为 srand48drand48 仅在 POSIX 系统上可用
【解决方案3】:

'c' stdlib rand() 返回一个介于 0 和 RAND_MAX 之间的数字,通常为 32767。

有什么理由不使用 python random() 吗?

Generate random integers between 0 and 9

【讨论】:

  • 我在 Cython 函数中使用了这个内部循环,为此调用 Python 成本太高
  • RAND_MAX 在我的系统上是 2147483647 (231-1)。它保证至少 215-1,但我认为我在实践中从未见过这么低的值。
  • 哦,显然 msvc 是 2**15-1。太可怕了。
  • 是的。有一个原因是时间减少。使用原生 C rand() 函数比使用 numpy.rand() 减少了 300 毫秒的时间。
猜你喜欢
  • 2017-04-20
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多