Как суммировать кусочек байтов, уменьшая вероятность переполнения - PullRequest
0 голосов
/ 12 ноября 2018

У меня есть фрагмент строки ASCII, и мне нужно вычислить сумму всех символов, когда они рассматриваются как байты.

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

Мне нужно указать тип для суммы, иначе Rust не скомпилируется. Проблема в том, что u8 слишком маленький тип, и если сумма переполняется, программа запаникует.

Я бы хотел этого избежать, но не могу найти способ указать больший тип, например u16 или u32, например, при использовании sum().

Я могу попытаться использовать fold(), но мне было интересно, есть ли способ использовать sum(), указав другой тип.

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

1 Ответ

0 голосов
/ 12 ноября 2018

Вы можете использовать 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 , который обеспечивает ее, имеет следующее определение:

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

Это означает, что его метод sum возвращает по умолчанию тот же тип, что и элементы итератора, из которого он построен. Вы можете увидеть, что это так с u8, посмотрев на реализацию Sum:

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