【问题标题】:Why is closed form for fibonacci sequence not used in practice?为什么在实践中不使用斐波那契数列的封闭形式?
【发布时间】:2021-12-09 12:26:22
【问题描述】:

斐波那契数列有一个封闭形式,可以通过generating functions 获得。它是:

f_n = 1/sqrt(5) (phi^n-\psi^n)

有关这些术语的含义,请参阅上面的链接或here。

然而,here 讨论过这种封闭形式并没有真正在实践中使用,因为当 n 变得大约 100 或更大时它开始产生错误的答案。

但在答案here 中,似乎采用的一种方法是快速矩阵求幂,它可用于在 O(log(n)) 时间内非常有效地获得第 n 个斐波那契数。

但是,封闭式表达式涉及到一堆被提升到 n 次方的项。因此,您可以通过快速取幂计算所有这些项,并以这种方式有效地得到结果。为什么对矩阵进行快速求幂比在封闭形式表达式中显示的标量上进行求幂更好?此外,为了寻找如何有效地对矩阵进行快速求幂,公认的答案here 建议我们转换为对角线形式并在标量上进行。

然后的问题是 - 如果矩阵的快速取幂有利于在 O(log(n)) 时间内计算第 n 个斐波那契数,那么当涉及快速取幂时,为什么封闭形式不是一种很好的方法在标量上?

【问题讨论】:

  • 与许多类似的问题一样,您只需尝试一下就可以很好地了解问题的某些方面。尝试使用封闭形式的 phi/psi 公式计算越来越大的值的答案,看看结果如何。
  • 当然。但我不怀疑我分享的第三个链接中的那个人,他说他在 n=80 左右遇到了溢出问题。我相信我会打同样的。只是,矩阵求幂方法从根本上避免了这种情况(并使结果保持更长时间的准确性)?特别是因为它似乎以更粗暴的方式做同样的事情。
  • 这并不是关于矩阵与标量,而是关于“标量”所指的内容。 Phi 是一个无理数;一个公式需要将浮点数精确地提高到非常大的幂,同时保持舍入误差非常低。 “矩阵”公式只使用整数乘法。
  • 封闭形式的解决方案需要对无理数(IEEE 浮点数不能精确表示)、高次幂(将很快超过可表示为 IEEE 浮点数的最大值)和减法运算两个非常大的数字(导致失去意义)。所有这些因素都会导致数值不稳定。整个工程领域被称为numerical analysis,致力于了解这些因素并努力避免它们。
  • @RaymondChen “封闭形式”解决方案从一个非常大的数字中减去一个非常小的数字,因此数值不稳定性不是问题。 (实际上,除了非常小的 n 之外,第二项小于 1/2,因此您可以忽略它,只需将第一项四舍五入到最接近的整数。)问题只是不完美的精度浮点数。

标签: sequence dynamic-programming fibonacci


【解决方案1】:

请注意,这里的“实践中”指的是竞争性编程(实际上,您基本上永远不想计算大量的斐波那契数)。所以,第一个原因是计算斐波那契数的正常方法是打字速度更快而不会出错,而且代码更少。另外,它会比处理小数字的花哨方法更快。

当涉及到大数字时,如果您不关心精度,那么快速矩阵乘法是 O(log(n))。然而,在竞争性编程中,我们几乎总是关心精度并想要正确的答案。为此,我们需要提高数字的精度。 n 越大,需要的精度就越高。我不知道确切的公式,但我想由于需要增加精度,只需要 O(log n) 乘法的矩阵乘法将需要 O(log n) 位精度,因此时间复杂度将实际上最终有点糟糕(O(log ^ 3 n)也许?)。更不用说,因为要乘以任意精度的数字,所以更难编码而且速度非常慢。

【讨论】:

    【解决方案2】:

    计算斐波那契数的“封闭形式”公式,您需要将无理数提高到幂 n,这意味着您必须接受仅使用近似值(通常是双精度浮点算术),因此对于大数的结果不准确。

    相反,在计算斐波那契数的“矩阵求幂”公式中,您要乘以 n 次方的矩阵是整数矩阵,因此您可以进行整数计算而不会损失精度使用“big int”库对任意大整数进行算术运算(或者如果您使用 Python 之类的语言,“big int”是默认值)。

    所以区别在于你不能用无理数做精确的算术,但你可以用整数。

    【讨论】:

      猜你喜欢
      • 2019-04-14
      • 2012-12-29
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      相关资源
      最近更新 更多