简体   繁体   中英

How to sum the values in an array, slice, or Vec in Rust?

Editor's note: This question's example is from a version of Rust prior to 1.0 and references types and methods no longer found in Rust. The answers still contain valuable information.

The following code

let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum(); 

results in the following error:

std::iter::Map<,&u8,u8,std::slice::Items<,u8>>` does not implement any method in scope named `sum`

What must I do to sum an array of bytes?

The following works:

for byte in new_serial.as_bytes().iter() {
    sum = sum + (byte - 48);
}

Iterator::sum was stabilized in Rust 1.11.0. You can get an iterator from your array/slice/ Vec and then use sum :

fn main() {
    let a = [1, 2, 3, 4, 5];
    let sum: u8 = a.iter().sum();
    println!("the total sum is: {}", sum);
}

Of special note is that you need to specify the type to sum into ( sum: u8 ) as the method allows for multiple implementations. See Why can't Rust infer the resulting type of Iterator::sum? for more information.


Applied to your original example:

let new_serial = "01234";
let sum: u8 = new_serial.as_bytes().iter().map(|&x| x - 48).sum();
println!("{}", sum);

As an aside, it's likely more clear if you use b'0' instead of 48 .

If performance is important, consider using an implementation that helps the compiler at producing SIMD instructions.

For example, for f32 , using 16 lanes (total of 512 bits):

use std::convert::TryInto;

const LANES: usize = 16;

pub fn nonsimd_sum(values: &[f32]) -> f32 {
    let chunks = values.chunks_exact(LANES);
    let remainder = chunks.remainder();

    let sum = chunks.fold([0.0f32; LANES], |mut acc, chunk| {
        let chunk: [f32; LANES] = chunk.try_into().unwrap();
        for i in 0..LANES {
            acc[i] += chunk[i];
        }
        acc
    });

    let remainder: f32 = remainder.iter().copied().sum();

    let mut reduced = 0.0f32;
    for i in 0..LANES {
        reduced += sum[i];
    }
    reduced + remainder
}

pub fn naive_sum(values: &[f32]) -> f32 {
    values.iter().sum()
}

for

let values = (0..513).map(|x| x as f32).collect::<Vec<_>>();

the above is 10x faster than values.iter().sum() on my computer:

nonsimd_sum             time:   [77.341 ns 77.773 ns 78.378 ns]
naive_sum               time:   [739.97 ns 740.48 ns 740.97 ns]

and ~10% slower than using packed_simd2 (but it does not require nightly).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM