2个版本
0.1.1 | 2024年2月4日 |
---|---|
0.1.0 | 2024年2月4日 |
#1242 in 算法
每月21次下载
31KB
562 行
pyrand
纯Rust实现Python的random模块(部分)的PRNG行为兼容:使用等效值进行播种将产生相同的PRNG输出。因此运行
import random
rng = random.Random("Pizza")
rng.choices(range(20), k=5)
将产生 [3, 3, 15, 2, 16]
和运行等效的
use pyrand::{PyMt19937, PySeedable, RandomChoiceIterator};
let rng = &mut PyMt19937::py_seed("Pizza");
assert_eq!((0..20).choose(rng).take(5).collect::<Vec<_>>(), vec![3, 3, 15, 2, 16]);
也将产生 [3, 3, 15, 2, 16]
。
这看起来很酷。为什么这必须是一个东西?
假设您已经编写了一些使用(伪)随机数的Python代码,例如
import random
random.seed(input("Enter seed: "))
# run some computations using random numbers
...
result = random.random()
print(f"Your result is: {result}")
并且您的用户以某种方式依赖于该结果。那么,如果用户提供了相同的输入,您的应用程序必须始终返回相同的确切值。这意味着您与Python及其当前的 random
实现紧密耦合。
我确实遇到了一些Python代码中存在这种情况的不幸情况。我想重写这段代码,但在没有同时引入Python来处理PRNG部分的情况下(或者静态链接CPython的部分等)根本无法实现 - 这会杀死整个重写。所以长话短说:我在Rust中重新实现了Python随机数生成代码的核心功能,确保两个实现之间保持一致的输出。
如果您确实需要为我尚未实现的一些函数提供此类兼容性,请随意实现它们并提交一个拉取请求 - 或者提交GitHub仓库的一个问题。
rand
支持
有一些(可选)对rand
特质的实现,但它们可能在基本内部生成器之上重新实现了某些“本地”可用的生成器,并且以与Python中实现不同的方式实现。这意味着如果您使用生成器的rand
接口,则必须验证您实际上是否获得了特定情况的匹配输出。
实现细节
实现基于 _randommodule.c
和 random.py
,我尽量保留了大部分函数和变量名等。基本算法是 32位梅森旋转算法(MT19937)。
依赖项
约1MB
约25K SLoC