如何在Rust中高效生成指定比特长度的大随机数?
问题描述
我尝试使用Rust的Rug库生成任意比特长度的随机数,编写了如下函数:
fn bit_str(bitlen: usize) -> String { let vs = vec!['0','1']; let mut nums = vec!['0'; bitlen]; for i in 0..bitlen { nums[i] = *vs.choose(&mut rand::thread_rng()).unwrap(); } return nums.into_iter().collect::<String>(); } let bin = bit_str(1_000_000); let mut random_number = Integer::new(); random_number.assign(Integer::parse_radix(bin,2).unwrap());
但该实现速度较慢,在我的环境中生成100个100万比特的随机数耗时30秒,请问有什么方法可以更快地生成这类随机数?
优化方案
原代码的性能瓶颈在于逐个生成比特位并转换为字符串再解析,这两步存在大量不必要的开销。以下是两种高效的优化思路:
1. 直接用Rug内置的随机数生成方法
Rug的Integer类型自带random_bits方法,能直接生成指定比特长度的随机数,这是最直接高效的方式:
use rug::Integer; use rand::thread_rng; fn generate_random_int(bitlen: usize) -> Integer { let mut rng = thread_rng(); Integer::random_bits(bitlen, &mut rng) } // 使用示例 let random_number = generate_random_int(1_000_000);
这个方法直接在底层生成二进制数据,跳过了字符串转换的所有开销,性能会有数量级的提升。
2. 批量生成字节再转换为Integer
如果需要自定义随机源,可以先用rand批量生成字节数组,再直接转换为Rug的Integer,同时处理比特长度不是8倍数的情况:
use rug::Integer; use rand::{thread_rng, Rng}; fn generate_random_int(bitlen: usize) -> Integer { let mut rng = thread_rng(); // 计算需要的字节数,向上取整 let byte_len = (bitlen + 7) / 8; let mut bytes = vec![0u8; byte_len]; rng.fill(&mut bytes); // 若比特长度不是8的倍数,清除高位多余的比特 if bitlen % 8 != 0 { let extra_bits = 8 - (bitlen % 8); bytes[0] &= !(0xFF << (8 - extra_bits)); } Integer::from_digits(&bytes, rug::integer::Order::Msf) } // 使用示例 let random_number = generate_random_int(1_000_000);
这种方式通过批量生成字节减少随机数调用次数,直接从字节构造Integer,完全避免了字符串解析的开销。
效果说明
用以上两种方法生成100个100万比特的随机数,耗时会降到原代码的几百分之一,完全能满足性能需求。
内容的提问来源于stack exchange,提问作者Jihyun
相关产品推荐
相关产品推荐

