Skip to content

Instantly share code, notes, and snippets.

@jamen
Last active May 5, 2020 23:27
Show Gist options
  • Save jamen/79ed78d969fd702c95475e5819c34c13 to your computer and use it in GitHub Desktop.
Save jamen/79ed78d969fd702c95475e5819c34c13 to your computer and use it in GitHub Desktop.
Count the digits of an integer in any base efficiently.
// We can use log2(x) = size_of(x) - 1 - clz(x).
// And then do a base conversion log_b(x) = log2(x) / log2(b).
// Then log_b(x) + 1 is the number of digits in base b for x > 0.
fn count_digits(x: usize, base: u8) -> usize {
1 + (8 * mem::size_of::<usize>() - 1 - x.leading_zeros() as usize) / (7 - base.leading_zeros() as usize)
}
// Say we know we're counting in base 10 or base 16. We can calculate the divisor.
fn count_base10_digits(x: usize) -> usize {
1 + (8 * mem::size_of::<usize>() - 1 - x.leading_zeros() as usize) / 3
}
// Rust and LLVM will calculate part of the dividend too
// But you can also do it yourself if the integer size is already clear.
fn count_base10_digits_u32(x: u32) -> u32 {
1 + (31 - x.leading_zeros()) / 3
}
// Here's another example of counting hex digits.
fn count_base16_digits_u32(x: u32) -> u32 {
1 + (31 - x.leading_zeros()) / 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment