【发布时间】:2015-10-07 01:16:05
【问题描述】:
我们如何在 Elixir 中有效地计算整数中的位数?
我在 Iex 的尝试
iex(1)> a=100_000
100000
iex(2)> Enum.reduce(1..a, &(&1*&2))|> to_string|> String.length
456574
iex(3)>
需要 15 秒
另一个实现:
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
慢得多:b = 100_000!
来自 cmets 的建议(感谢 Fred!)
iex> Integer.to_char_list(b) |> length
目前为止最好最简单的
IEx> :timer.tc(fn -> Demo.cnt b end)
{277662000, 456574}
IEx> :timer.tc(fn ->b |> to_string |> String.length end)
{29170000, 456574}
在任何 Elixir 模块中是否为此内置了 wizardry?
【问题讨论】:
-
提示:math.log10(10) = 1;数学.log10(100) = 2;数学.log10(789) = 2.897。你能看出以 10 为基数的 log 与位数之间的关系吗?您还需要使用 floor 函数。
-
显然你可以使用 Erlang 的库 - 搜索“elixir 数学库”。我对Elixir一无所知。哦,而不是
floor,您似乎可以使用trunc更简洁。 -
大声笑,估计是less than 10^90 neutrinos in the universe(他们的数量超过了photons) - 你真的需要能够处理大于 10^308 的数字吗?
-
FWIW 使用 to_char_list 和长度稍快。
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} -
关于代码格式的一个小而愚蠢的建议@CharlesO:a = 100_000 与其他方式一样有效,并且更易于阅读。使用“_”作为分隔符对 Elixir 没有任何影响,但它减少了有人将零数错的可能性。