实现Atkin筛法时,如何在Vector/BitVec容量增长时触发panic!?
可行,实现方案如下
核心思路
通过提前初始化足够容量的容器,并在操作中严格限制触发扩容的行为,一旦检测到容量增长则直接panic,以此验证算法的正确性。
1. BitVec 的处理
BitVec 的大小在函数调用时即可确定,因此初始化时直接分配足够容量,且仅通过索引操作修改元素,避免调用任何会触发扩容的方法(如push、extend):
- 用
BitVec::from_elem(limit as usize, false)或BitVec::with_capacity+resize初始化,确保初始容量等于目标上限limit; - 算法中仅使用
set/get通过索引修改、访问元素,杜绝扩容可能; - 可选:在算法关键节点主动检查
BitVec的容量是否等于初始值,不等则panic。
2. 质数 Vector 的处理
质数数量可通过近似公式提前估算上限,初始化时将容量设为该上限,再通过自定义的安全push方法避免扩容:
- 估算质数数量:使用更精确的近似公式(如
n / (ln n - 1.08366),适用于n >=10;小数字直接返回已知质数数量),确保初始容量足够容纳所有结果; - 安全push封装:每次push前检查当前长度是否小于容量,若超出则直接panic,避免触发Vec的自动扩容;
- 可选:在算法结束前检查Vector容量是否等于初始值,确保未发生扩容。
代码示例
use bitvec::prelude::*; // 近似计算小于n的质数数量 fn approximate_prime_count(n: u64) -> usize { if n < 2 { return 0; } let ln_n = (n as f64).ln(); if n >= 10 { (n as f64 / (ln_n - 1.08366)) as usize } else { match n { 2 => 0, 3 => 1, 4 => 2, 5 => 2, 6 => 3, 7 => 3, 8 => 4, 9 => 4, _ => unreachable!(), } } } // 安全push质数,容量不足则panic fn push_prime(primes: &mut Vec<u64>, p: u64) { if primes.len() >= primes.capacity() { panic!("Prime vector capacity exceeded - algorithm error detected!"); } primes.push(p); } fn atkin_sieve(limit: u64) -> Vec<u64> { if limit <= 2 { return Vec::new(); } // 初始化BitVec,容量等于limit,初始值为非质数 let mut sieve = BitVec::from_elem(limit as usize, false); let initial_sieve_cap = sieve.capacity(); // Atkin筛法核心逻辑(示例) sieve.set(2, true); sieve.set(3, true); // ... 省略其余筛法步骤 // 检查BitVec容量是否未变化 if sieve.capacity() != initial_sieve_cap { panic!("Sieve BitVec capacity unexpectedly grew - algorithm error!"); } // 初始化质数Vector,设置预估容量 let approx_count = approximate_prime_count(limit); let mut primes = Vec::with_capacity(approx_count); let initial_primes_cap = primes.capacity(); // 收集质数 for i in 2..limit { if sieve[i as usize] { push_prime(&mut primes, i); } } // 检查质数Vector容量是否未变化 if primes.capacity() != initial_primes_cap { panic!("Prime vector capacity unexpectedly grew - algorithm error!"); } primes.shrink_to_fit(); primes }
注意事项
- 质数数量的近似公式需足够精确,否则会提前触发panic,可根据实际测试调整公式参数;
- BitVec操作必须严格避免扩容方法,确保仅通过索引修改元素;
- 主动检查容量的步骤可根据算法复杂度调整位置,比如批量处理后或算法结束前。
内容的提问来源于stack exchange,提问作者Pioneer_11
相关产品推荐
相关产品推荐

