#integer #digits #length #traits #count #decimal-digits

no-std count-digits

一个不使用std的特质,用于确定各种数制下整数的长度

13个版本 (4个重大更改)

0.5.1 2024年2月11日
0.5.0 2024年2月9日
0.4.0 2024年2月8日
0.3.1 2024年2月8日
0.1.0 2024年1月23日

#429 in 算法

Download history 29/week @ 2024-03-10 85/week @ 2024-03-31 24/week @ 2024-05-05 1/week @ 2024-06-02 13/week @ 2024-06-09 25/week @ 2024-06-16 39/week @ 2024-06-23

每月下载量78
用于 visu

MIT 许可证

89KB
946

count-digits

github crates-io docs-rs

license build codecov


CountDigits 是一个不使用std的特质,包含用于确定各种数制下整数长度的函数。

它适用于所有原始整数类型以及所有非零整数类型。

pub trait CountDigits: Copy + Sized {
    /// The type of integer that should be used for radix arguments.
    type Radix;

    /// Returns the count of bits in an integer.
    fn count_bits(self) -> u32;

    /// Returns the count of octal digits in an integer.
    fn count_octal_digits(self) -> u32;

    /// Returns the count of hexadecimal digits in an integer.
    fn count_hex_digits(self) -> u32;

    /// Returns the count of decimal digits in an integer.
    fn count_digits(self) -> usize;

    /// Returns the count of digits in an integer for a given radix.
    /// Panics if the provided radix is invalid.
    fn count_digits_radix(self, radix: Self::Radix) -> usize;

    /// Returns the count of digits in an integer for a given radix.
    /// Returns None if the given radix is invalid.
    fn checked_count_digits_radix(self, radix: Self::Radix) -> Option<usize>;
}

示例

use count_digits::CountDigits;

// Base 2
assert_eq!(16, 0b1111000000001101.count_bits());
assert_eq!(16, 0b1111000000001101.count_digits_radix(2_u32));

// Base 8
assert_eq!(06, 0o170015.count_octal_digits());
assert_eq!(06, 0o170015.count_digits_radix(8_u32));

// Base 10
assert_eq!(05, 61453.count_digits());
assert_eq!(05, 61453.count_digits_radix(10_u32));

// Base 16
assert_eq!(04, 0xF00D.count_hex_digits());
assert_eq!(04, 0xF00D.count_digits_radix(16_u32));

返回u32的函数

名称函数,其中基数是2的幂,返回u32,以兼容Rust的位操作函数和常量。

assert_eq!(0b1011___u8.count_bits(),   u8::BITS - 0b1011___u8.leading_zeros());
assert_eq!(0b1011__i32.count_bits(),  i32::BITS - 0b1011__i32.leading_zeros());
assert_eq!(0b1011_u128.count_bits(), u128::BITS - 0b1011_u128.leading_zeros());

返回usize的函数

不是位操作上下文中固有意义的函数返回usize,以兼容Rust的格式化函数和宏。

let numbers = [2, 3, 13, 103, 1337];
let max_digits = numbers
    .iter()
    .map(CountDigits::count_digits)
    .max()
    .unwrap();

for n in numbers {
    assert_eq!(4, format!("{n:>max_digits$}").chars().count());
}

在格式化二进制、八进制或十六进制数字时,可以使用count_digits_radix(2 | 8 | 16)checked_count_digits_radix(2 | 8 | 16)函数代替count_bits()count_octal_digits()count_hex_digits(),直接以usize获取所需计数。

let numbers = [0b1, 0b10, 0b101, 0b1011];
let max_bits = numbers
    .iter()
    .map(|n| n.count_digits_radix(2u32))
    .max()
    .unwrap();

for n in numbers {
    assert_eq!(4, format!("{n:>max_bits$}").chars().count());
}

无效的基数值

传递给count_digits_radix()checked_count_digits_radix()的值必须大于或等于2。

for n in 0..100 {
    assert!(std::panic::catch_unwind(|| n.count_digits_radix(0_u32)).is_err());
    assert!(std::panic::catch_unwind(|| n.count_digits_radix(1_u32)).is_err());
}
for n in 0..100 {
    assert!(n.checked_count_digits_radix(0_u32).is_none());
    assert!(n.checked_count_digits_radix(1_u32).is_none());
}

负数

由于用十进制表示的负数会显示负号,所以正数的十进制位数将与该数的相反数的十进制位数相等,前提是没有发生卷绕。

请注意,负号本身不包括在计数中,因为负号不是一个数字。

assert_eq!(
    867_5309_i32.count_digits(),
    867_5309_i32.wrapping_neg().count_digits(),
);

用其他基数表示的负数的位数反映了 二进制补码 表示,正数的位数将 与其相反数的位数相同。

for radix in 2..=16 {
    match radix {
        10 => assert_eq!(
            0xF00D_i32.count_digits_radix(radix),
            0xF00D_i32.wrapping_neg().count_digits_radix(radix),
        ),
        _ => assert_ne!(
            0xBAD_i32.count_digits_radix(radix),
            0xBAD_i32.wrapping_neg().count_digits_radix(radix),
        ),
    }
}

这与 Rust 的显示格式一致。

// Base 2
assert_eq!(01, format!("{:b}",  1_i32).chars().count());
assert_eq!(32, format!("{:b}", -1_i32).chars().count());

// Base 8
assert_eq!(01, format!("{:o}",  1_i32).chars().count());
assert_eq!(11, format!("{:o}", -1_i32).chars().count());

// Base 10
assert_eq!(01, format!("{  }",  1_i32).chars().count());
assert_eq!(01, format!("{  }", -1_i32).strip_prefix('-').unwrap().chars().count());

// Base 16
assert_eq!(01, format!("{:x}",  1_i32).chars().count());
assert_eq!(08, format!("{:x}", -1_i32).chars().count());

基准测试

许可:MIT

无运行时依赖