🦀

Rustで数字の各桁をVecに格納する

2022/05/02に公開

Codewarsの「Convert number to reversed array of digits」を解いていて、数字の各桁をVecに格納するのに2通りの方法を思いついたのでメモしておく。ついでにベンチも取ってみた。
https://www.codewars.com/kata/5583090cbe83f4fd8c000051/rust

解法

// 1. 愚直に割り算をしていく
fn divide_digitize(n: u64) -> Vec<u8> {
    if n > 0 {
        let mut num = n;
        let mut result = Vec::new();
        while num != 0 {
            result.push((num % 10).try_into().unwrap());
            num /= 10;
        }
        result.reverse();
        result
    } else {
        vec![0]
    }
}
// assert_eq!(divide_digitize(12345678), vec![1, 2, 3, 4, 5, 6, 7, 8]);

// 2. 一旦Stringにしてから1文字ずつ処理する
fn string_digitize(n: u64) -> Vec<u8> {
    n.to_string()
        .chars()
        .into_iter()
        .map(|char| char.to_digit(10).unwrap() as u8)
        .collect()
}
// assert_eq!(string_digitize(12345678), vec![1, 2, 3, 4, 5, 6, 7, 8]);

ベンチマーク

benchは2022/05/02時点でnightlyなので注意。

コード

#![feature(test)]
extern crate test;

#[cfg(test)]
mod tests {
    use super::*;
    #[bench]
    fn divide(b: &mut test::Bencher) {
        b.iter(|| divide_digitize(12345352313523135231));
    }

    #[bench]
    fn string(b: &mut test::Bencher) {
        b.iter(|| string_digitize(12345352313523135231));
    }
}

ベンチ結果

test tests::divide ... bench:         153 ns/iter (+/- 5)
test tests::string ... bench:         180 ns/iter (+/- 4)

まとめ

Stringに変換するよりも、愚直に割っていく方が処理速度が速かった。
直観的には愚直に割っていくほうが遅い気がするのだが、ベンチ関数で渡す数字を123程度に小さくしてみても結果は変わらなかった。

Discussion