【发布时间】:2015-08-15 11:13:59
【问题描述】:
如何在 Elixir 中计算具有指数的数字?
例如,23 将返回 8。
【问题讨论】:
标签: elixir
如何在 Elixir 中计算具有指数的数字?
例如,23 将返回 8。
【问题讨论】:
标签: elixir
【讨论】:
Erlang 的:math.pow 有一些限制,例如它不允许使用非常高的整数指数:
iex(10)> :math.pow(2, 10000)
** (ArithmeticError) bad argument in arithmetic expression
您可以轻松地重新实现一个快速算法来计算指数,该算法适用于运行时提供的任意大整数:
defmodule Pow do
require Integer
def pow(_, 0), do: 1
def pow(x, n) when Integer.is_odd(n), do: x * pow(x, n - 1)
def pow(x, n) do
result = pow(x, div(n, 2))
result * result
end
end
iex(9)> Pow.pow(2, 10000)
19950631168807583848837421626835850838234968318861924548520089498529438830...
【讨论】:
这里是幂函数的尾调用优化实现:
def pow(n, k), do: pow(n, k, 1)
defp pow(_, 0, acc), do: acc
defp pow(n, k, acc), do: pow(n, k - 1, n * acc)
【讨论】:
:math.pow 的当前实现替换为对此的 Erlang 翻译会很好。 github.com/erlang/otp
从 v1.12 开始,Integer.pow/2 是执行此操作的方法。
【讨论】:
:math.pow/2
【讨论】:
> elixir -v Elixir 1.13.0-rc.0 (5062a15) (compiled with Erlang/OTP 22) 和 iex 控制台:iex(1)> 2 ** 4 输出 16
如果底数是 2 并且幂是整数,您可以使用函数 Bitwise.bsl 进行左位移。例如,23 可以这样计算:
> Bitwise.bsl(1, 3)
8
【讨论】:
这是有效的——当我学到足够多的知识来确切地知道它为什么有效时会很棒——可能与幕后的 eval 有关:
defmodule Example do
require Integer
def do_it(list) do
list
|> Enum.reject(&Integer.is_odd(&1))
|> Enum.map(&(:math.pow(&1,3)))
end
end
【讨论】: