【问题标题】:Vector index "out of bounds" when converting large floating point numbers to integer indices将大浮点数转换为整数索引时,向量索引“越界”
【发布时间】:2016-01-29 02:52:48
【问题描述】:

我一直在尝试使用以下函数在 m 和 n 之间生成素数:

//the variable sieve is a list of primes between 1 and 32000
//The primes up to 100 are definitely correct
fn sieve_primes(sieve: &Vec<usize>, m: &usize, n: &usize) -> Vec<usize> {
    let size: usize = *n - *m + 1;
    let mut list: Vec<usize> = Vec::with_capacity(size);

    for i in *m..(*n + 1) {
        list.push(i);
    }   
    for i in sieve {
        for j in ( ((*m as f32) / (*i as f32)).ceil() as usize)..( (((*n as f32) / (*i as f32)).floor() + 1.0) as usize) {
                println!("{} ",j);
                if j != 1 {list[i * j - *m] = 0;} 
        }
    }   

    let mut primes: Vec<usize> = Vec::new();
    for num in &list{
        if *num >= 2 {primes.push(*num);}
    }   
    primes
}

这适用于较小(小于 1000000-ish)的 m 和 n 值,但是 它在运行时失败,数量约为数十亿/亿。

m = 99999999, n = 100000000 的输出为:

33333334
线程 '' 在 'index out of bounds: the len is 2 but index is 3' 时惊慌失措

如果您查看数字,这没有任何意义。首先,它似乎跳过了素数列表中的数字 2。其次,当 i = 3 时,for 语句应该简化为 for j in 33333333..333333334,由于某种原因,它从 33333334 开始 j。

【问题讨论】:

    标签: rust


    【解决方案1】:

    f32只能精确表示所有的24位整数,大约对应1600万(实际是16777216)。上面还有差距,最多只能表示 33554432 个偶数。因此,在您的示例中,33333333 不能表示为 f32,而是四舍五入为 33333334。

    您不需要使用浮点数来舍入整数除法的结果。直接使用整数既快又不存在精度问题。对于非负整数,您可以执行以下操作:

    fn main() {
        let a = 12;
        let b = 7;
        println!("rounded down: {}", a / b);
        println!("rounded:      {}", (a + b / 2) / b);
        println!("rounded up:   {}", (a + b - 1) / b);
    }
    

    【讨论】:

      【解决方案2】:

      您将整数转换为f32,但f32 不够精确。请改用f64

      fn main() {
          println!("{}", 33333333.0f32); // prints 33333332
      }
      

      【讨论】:

        猜你喜欢
        • 2013-07-27
        • 2010-10-14
        • 1970-01-01
        • 2018-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多