如何对一片字节进行求和,减少溢出的可能性

Nic*_*ick 4 string byte sum slice rust

我有一个ASCII字符串切片,我需要计算所有字符的总和,当看作字节.

let word = "Hello, World";
let sum = word.as_bytes().iter().sum::<u8>();
Run Code Online (Sandbox Code Playgroud)

我需要指定sum的类型,否则Rust将无法编译.问题是这u8是一个太小的类型,如果总和溢出程序将会出现恐慌.

我想避免这种情况,但我无法找到一种方法来指定更大的类型,例如,u16或者u32在使用时sum().

我可能会尝试使用fold(),但我想知道是否有一种方法可以sum()通过指定另一种类型来使用.

let sum = word.as_bytes().iter().fold(0u32, |acc, x| acc + *x as u32);
Run Code Online (Sandbox Code Playgroud)

lje*_*drz 6

您可以使用map将每个字节强制转换为更大的类型:

let sum: u32 = word.as_bytes().iter().map(|&b| b as u32).sum();
Run Code Online (Sandbox Code Playgroud)

要么

let sum: u32 = word.as_bytes().iter().cloned().map(u32::from).sum();
Run Code Online (Sandbox Code Playgroud)

您无法总结u32使用原始尝试的原因是提供它的Sum特征具有以下定义:

pub trait Sum<A = Self> {
    fn sum<I>(iter: I) -> Self
    where
        I: Iterator<Item = A>;
}
Run Code Online (Sandbox Code Playgroud)

这意味着它的方法sum默认返回与构建它的迭代器的项相同的类型.你可以看到它是一个与案件u8通过观察其执行Sum:

fn sum<I>(iter: I) -> u8
where
    I: Iterator<Item = u8>,
Run Code Online (Sandbox Code Playgroud)

  • 他们可能编译成完全相同的代码. (3认同)
  • 我只是试着看着集会.在使用优化进行编译时,编译器确实[生成完全相同的代码](https://play.rust-lang.org/?version=stable&mode=release&edition=2015&gist=6bc9e1d988e1f00fc1b9d5eca59ddc95).对于私有函数,编译器只是删除其中一个函数,因为它们是相同的.当我尝试使用固定字符串时,编译器在编译时计算了总和,并且为该函数发出的唯一代码是`movd eax,1234; ret`或类似的,所以我添加了代码来生成随机字符串. (3认同)
  • @Nick TBH,我不知道为什么没有添加扩展版本.我认为只是没有人做过.也许您可以提交拉取请求来添加它们! (2认同)