【问题标题】:How to sum a slice of bytes reducing the possibility of overflow如何对一片字节求和以减少溢出的可能性
【发布时间】:2019-04-15 14:40:35
【问题描述】:

我有一个 ASCII 字符串切片,当被视为字节时,我需要计算所有字符的总和。

let word = "Hello, World";
let sum = word.as_bytes().iter().sum::<u8>();

我需要指定 sum 的类型,否则 Rust 将无法编译。问题是u8是一个太小的类型,如果和溢出程序会死机。

我想避免这种情况,但我找不到一种方法来指定更大的类型,例如 u16u32,例如,在使用 sum() 时。

我可能会尝试使用fold(),但我想知道是否可以通过指定其他类型来使用sum()

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

【问题讨论】:

    标签: string rust sum byte slice


    【解决方案1】:

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

    let sum: u32 = word.as_bytes().iter().map(|&b| b as u32).sum();
    

    let sum: u32 = word.as_bytes().iter().cloned().map(u32::from).sum();
    

    您无法使用原始尝试求和到u32 的原因是提供它的Sum trait 具有以下定义:

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

    这意味着它的方法sum 默认返回与构建它的迭代器的项目相同的类型。通过查看implementation of Sum,您可以看到u8 的情况:

    fn sum<I>(iter: I) -> u8
    where
        I: Iterator<Item = u8>,
    

    【讨论】:

    • 在内存使用和性能方面,您的解决方案与折叠解决方案有何不同?
    • 最好谈谈为什么 OP 不能像他们最初尝试的那样做word.as_bytes().iter().sum::&lt;u32&gt;()
    • 我刚刚尝试并查看了程序集。使用优化编译时,编译器确实generates exactly the same code。对于私有函数,编译器只需删除其中一个,因为它们是相同的。当我尝试使用固定字符串时,编译器会在编译时计算总和,并且为该函数发出的唯一代码是 movd eax, 1234; ret 或类似代码,因此我添加了代码以生成随机字符串。
    • @SvenMarnach 如果您放弃 main 并将函数公开,您可以避免内联。
    • @Nick TBH,我不知道为什么没有添加加宽版本。我想只是还没有人做过。也许你可以提交一个拉取请求来添加它们!
    猜你喜欢
    • 1970-01-01
    • 2012-06-11
    • 2022-12-18
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多