3
votes

How can we efficiently count the digits in an integer in Elixir?

My attempt in Iex

iex(1)> a=100_000                                               
100000
iex(2)> Enum.reduce(1..a, &(&1*&2))|> to_string|> String.length
456574
iex(3)> 

Takes over 15 seconds

Another Implementation:

defmodule Demo do
    def cnt(n), do: _cnt(n,0)
    defp _cnt(0,a), do: a
    defp _cnt(n,a),do: _cnt(div(n,10),a+1)
end

Is way slower: b = 100_000!

A suggestion from the comments (Thanks Fred!)

iex> Integer.to_char_list(b) |> length

Is best so far and simplest

IEx> :timer.tc(fn -> Demo.cnt b  end)
{277662000, 456574}
IEx> :timer.tc(fn ->b |> to_string |> String.length end) 
{29170000, 456574}

Is there built in wizardry for this in any Elixir module?

1
Hint: math.log10(10) = 1; math.log10(100) = 2; math.log10(789) = 2.897. Can you see the relationship between the log to base 10 of a number and the number of digits? You will also want to use the floor function. - Andrew Morton
Apparently you can use libraries from Erlang - search for "elixir math library". I know nothing about Elixir. Oh, and instead of floor it appears that you can use trunc to be more succinct. - Andrew Morton
Lol, there are reckoned to be less than 10^90 neutrinos in the universe (they outnumber the photons) - do you really need to be able to work with numbers larger than 10^308? - Andrew Morton
FWIW using to_char_list and length is slightly faster. iex(10)> :timer.tc( fn -> Integer.to_string(b_fact) |> String.length end ) {16825611, 456574} iex(11)> :timer.tc( fn -> Integer.to_char_list(b_fact) |> length end ) {16704290, 456574} - Fred the Magic Wonder Dog
One small, dumb suggestion @CharlesO on code formatting: a = 100_000 works just as well as the other way and it's easier to read. Using the "_" as a separator makes no difference to Elixir but it makes it less likely that someone will miscount the zeroes. - Onorio Catenacci

1 Answers

1
votes

From Elixir 1.1 and above there is now a built in feature

Integer.digits/2

This effectively handles digit counting