Performance 为什么在长生不老药中大量电源超时?

Performance 为什么在长生不老药中大量电源超时?,performance,elixir,bitcoin,Performance,Elixir,Bitcoin,我正在尝试用长生不老药重现比特币的一些基础知识。我知道长生不老药不是完成任务的理想语言,但我这么做是为了好玩和学习。我在尝试从一个秘密中派生公钥时遇到了以下问题,这个秘密包括有限域上的一个非常大的数的一个非常大的幂。我自己实现了这个,因为math.pow/2已经在与相对较小的数字作斗争了。但是我的实现花费了非常长的时间,函数最终超时 值并调用函数: prime = 115792089237316195423570985008687907853269984665640564039457584007

我正在尝试用长生不老药重现比特币的一些基础知识。我知道长生不老药不是完成任务的理想语言,但我这么做是为了好玩和学习。我在尝试从一个秘密中派生公钥时遇到了以下问题,这个秘密包括有限域上的一个非常大的数的一个非常大的幂。我自己实现了这个,因为math.pow/2已经在与相对较小的数字作斗争了。但是我的实现花费了非常长的时间,函数最终超时

值并调用函数:

prime = 115792089237316195423570985008687907853269984665640564039457584007908834671663
val = 65341020041517633956166170261014086368942546761318486551877808671514674964848

Util.my_fpow(val, prime - 2, prime)
Util模块中的my_fpow/3方法:

defmodule Util do
  def my_fpow(n, k, prime), do: my_fpow(n, k, 1, prime)
  defp my_fpow(_, 0, acc, _), do: acc
  defp my_fpow(n, k, acc, prime) do
    new_acc = n * acc
              |> rem(prime)

    my_fpow(n, k - 1, new_acc, prime)
  end
end

首先,我想从更深层次上理解为什么这个方法需要如此长的时间来处理这些大数字。此外,我还想知道是否还有其他更有效的实现,可能仍然可以使用Elixir进行此类计算(不是按比例,只是为了让计算能够在超时之前完成)。

您的函数将递归
素数-2次,因为您一次减去1。即使Elixir每秒执行10亿次调用(在当前硬件上不会),执行也需要10^60年以上的时间

这是一个速度更快的解决方案,它减少了对
log2(x)
的调用次数,速度非常快。下面是该算法的翻译:

defmodule A do
  # Calculates (n ^ k) % m.
  def powmod(n, k, m), do: powmod(n, k, m, 1)
  def powmod(_, 0, _, r), do: r
  def powmod(n, k, m, r) do
    r = if rem(k, 2) == 1, do: rem(r * n, m), else: r
    n = rem(n * n, m)
    k = div(k, 2)
    powmod(n, k, m, r)
  end
end

prime = 115792089237316195423570985008687907853269984665640564039457584007908834671663
val = 65341020041517633956166170261014086368942546761318486551877808671514674964848

IO.inspect A.powmod(val, prime - 2, prime)
输出:

83174505189910067536517124096019359197644205712500122884473429251812128958118

rem/2
功能可能是你的瓶颈-看看哪一个不使用长生不老药。太棒了!这对我帮助很大。任何其他想要了解此操作的原因和方式的人,都应该在这里查看公式的详细分解,包括python版本的代码: