This code counts the number of digits in an integer.
let digitCount number = (int) (log10 ((float)number)) + 1;
For instance, it tells us 123456789 has 9 digits
.
let input = 123456789;
printfn "%i has %i digits" input (digitCount input);
https://dotnetfiddle.net/nxuoah
A weakness of the code is that it uses two casts. Can we use math to count the number of digits in an integer without having to cast twice? The reason to cast to a float is to make the type compatible with a the log10
function. The reason to cast back in to an integer
is to represent a "count" of digits instead of a "measure" of digits.
A second, related weakness of the code is the number of parentheses, which makes the code more difficult to read.
1 Answer 1
Your code contains a bug. What happens if number
is 0
? log10 0
should return -Infinity
, so we end up with the smallest int
plus one. Therefore, we need to check whether input
is 0
first:
let digitCount number = if number == 0 then 1 else (int) (log10 ((float)number)) + 1;
At that point we're not really succinct anymore, so there's no harm in using a recursive function instead:
let rec digitCount number = if number < 10 then 1 else 1 + digitCount (number / 10)
However, that's not tail recursive, so we would want to rewrite it using a loop
that's tail recursive. That's left as an exercise, though.
That being said, one can optimize counting digit a lot.
Andrei Alexandrescu held a talk about optimizing digits_base_10
in C++ several years ago. The original talk is offline, unfortunately, but the slides are still there.
log10
seems like overkill. You can do this recursively by dividing (well, integer division) the number by 10 repeatedly. \$\endgroup\$