英文:
generate a random number with given bit size in Rust
问题
我正在尝试使用Rug在Rust中生成任意位数的随机数。我创建了一个像这样的函数:
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());
但这很慢。在我的环境中,生成1百万位的100个随机数需要30秒。有没有办法更快地生成这样的随机数?
英文:
I am trying to generate a random number with aribitorary bit size in Rust using Rug. I create a function like this:
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());
But this is slow. In my environment, it took 30 seconds to generate 100 random numbers with 1m bits. Is there any way to generate such random numbers faster?
答案1
得分: 3
这个答案类似于apilat的答案,但使用了 rug
并生成尽可能大的块(最多 32 位,这是 rug::rand::RandState::bits
支持的最大值):
/*
[dependencies]
rug = "*"
*/
fn rand(mut bits: u32) -> rug::Integer {
let mut rand = rug::rand::RandState::new();
let mut res = rug::Integer::with_capacity(bits as usize);
while bits > 0 {
let generate = bits.min(32);
res = (res << generate) + rand.bits(generate);
bits -= generate;
}
res
}
fn main() {
println!("{:b}", rand(1_000_000));
}
[Rustexplorer.](https://www.rustexplorer.com/b#%2F*%0A%5Bdependencies%5D%0Arug%20%3D%20%22*%22%0A*%2F%0A%0Afn%20rand(mut%20bits%3A%20u32)%20-%3E%20rug%3A%3AInteger%20%7B%0A%20%20%20%20let%20mut%20rand%20%3D%20rug%3A%3Arand%3A%3ARandState%3A%3Anew()%3B%0A%0A%20%20%20%20let%20mut%20res%20%3D%20rug%3A%3AInteger%3A%3Awith_capacity(bits%20as%20usize)%3B%0A%0A%20%20%20%20while%20bits%20%3E%200%20%7B%0A%20%20%20%20%20%20%20%20let%20generate%20%3D%20bits.min(32)%3B%0A%0A%20%20%20%20%20%20%20%20res%20%3D%20(res%20%3C%3C%20generate)%20%2B%20rand.bits(generate)%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20bits%20-%3D%20generate%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20res%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!("{:b}", rand(1_000_000));%0A%7D)
英文:
This answer is akin to apilat's, but uses rug
and generates as big of chunks as possible (at most 32 bits, which is the maximum rug::rand::RandState::bits
supports):
/*
[dependencies]
rug = "*"
*/
fn rand(mut bits: u32) -> rug::Integer {
let mut rand = rug::rand::RandState::new();
let mut res = rug::Integer::with_capacity(bits as usize);
while bits > 0 {
let generate = bits.min(32);
res = (res << generate) + rand.bits(generate);
bits -= generate;
}
res
}
fn main() {
println!("{:b}", rand(1_000_000));
}
答案2
得分: 1
在一般情况下,直接使用整数比使用字符串然后转换要快得多。
将比特 b
追加到现有数字 x
的操作可以通过将 x
向左位移一位,然后加上 b
来实现:(x << 1) + b
。这是下面实现的原理。
我找不到你的 Integer
类型是从哪里来的,所以示例(playground)使用了 num::BigInt
。
你可以通过以更大的块生成比特(例如 32 或 64 位)来使这段代码运行得更快,尽管会增加一些实现复杂性。
use num::BigInt;
use rand::{Rng, thread_rng};
fn randint(bits: usize) -> BigInt {
let mut rng = thread_rng();
let mut x = BigInt::default();
for _ in 0..bits {
x <<= 1;
x += rng.gen_range(0..=1);
}
x
}
fn main() {
let x = randint(10);
let y = randint(1000);
println!("{x}");
println!("{y}");
}
英文:
In general, working with integers directly is much faster than working with strings and then converting.
The operation of appending a bit b
at the end of an existing number x
can be implemented by bit-shifting x
one to the left and then adding b
: (x << 1) + b
.
This is the principle behind the implementation below.
I couldn't figure out where your Integer
type comes from so the example (playground) uses num::BigInt
instead.
You could make this code even faster by generating bits in larger chunks (for example 32 or 64 bits) at the cost of some implementation complexity.
use num::BigInt;
use rand::{Rng, thread_rng};
fn randint(bits: usize) -> BigInt {
let mut rng = thread_rng();
let mut x = BigInt::default();
for _ in 0..bits {
x <<= 1;
x += rng.gen_range(0..=1);
}
x
}
fn main() {
let x = randint(10);
let y = randint(1000);
println!("{x}");
println!("{y}");
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论