如何在Rust中对数组,切片或Vec中的值求和?

rog*_*rgl 5 rust

编者注:该问题的示例来自1.0之前的Rust版本,并引用了Rust中不再存在的类型和方法。答案仍然包含有价值的信息。

以下代码

let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum(); 
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum(); 
Run Code Online (Sandbox Code Playgroud)

对字节数组求和应该怎么做?

以下作品:

for byte in new_serial.as_bytes().iter() {
    sum = sum + (byte - 48);
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*gan 7

Iterator::sum在Rust 1.11.0中已稳定。您可以从数组/ slice /中获得一个迭代器Vec,然后使用sum

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

特别要注意的是,sum: u8由于该方法允许多种实现,因此您需要指定要累加到()中的类型。请参阅为什么Rust无法推断出Iterator :: sum的结果类型?想要查询更多的信息。


应用于您的原始示例:

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

顺便说一句,如果您使用b'0'而不是,可能会更清楚48


Jor*_*tao 7

如果性能很重要,请考虑使用有助于编译器生成 SIMD 指令的实现。

例如,对于f32,使用 16 个通道(总共 512 位):

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()
}
Run Code Online (Sandbox Code Playgroud)

为了

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

以上比values.iter().sum()我的电脑快 10 倍:

nonsimd_sum             time:   [77.341 ns 77.773 ns 78.378 ns]
naive_sum               time:   [739.97 ns 740.48 ns 740.97 ns]
Run Code Online (Sandbox Code Playgroud)

并且比使用慢约 10% packed_simd2(但它不需要每晚使用)。