【问题标题】:computing large roots : bigdecimal / java计算大根:bigdecimal / java
【发布时间】:2010-01-24 18:05:15
【问题描述】:

我尝试使用标准迭代算法来计算第 n 个根。

例如 (111^123)^(1/123)。

标准算法计算基数的高次幂 (在本例中为 111^123),这需要很长时间。算法在这里给出http://en.wikipedia.org/wiki/Nth_root_algorithm

但是,我注意到使用 double 执行相同的操作不到一毫秒。所以很明显他们使用了一些聪明的想法。对此有何提示?

【问题讨论】:

  • 有人有什么好主意吗?我尝试了以下。为了计算a^(1/x)x 整数的大a, x,我计算了一个随机的b 使得b^x < ab^(x+1)>a。让c=a/b^x。我计算了a^(1/x) = (a*b^x/(b^x))^(1/x) = c^(1/x)*b。我希望通过保持基数c 小,我可以获得一些时间。不幸的是,如果我保持除法的比例很小,我会在计算c^(1/x) 时得到除以零错误,或者如果我保持这个比例很大,则计算时间会很长。所以这不买任何东西。
  • 通过使 b 更小,我得到了一些改进(从几小时到几分钟)。即b^x<a < b^(x+sqrt(x))。几分钟的时间还不够短。

标签: java root bigdecimal


【解决方案1】:

但是,我注意到同样的事情 使用 double 需要少于 a 毫秒。所以很明显他们使用 一些聪明的想法。

不是真的。 double 只是精度有限,所以它基本上只需要计算结果的最高有效 52 位,并且可以跳过其余的计算。当然,在硬件中实现这一点也有帮助。

【讨论】:

  • 是的,有限的精度可能是double 快速的原因。我应该自己想出来的 :-) 我真正需要的是一个聪明的算法来保持精度并快速计算大根。但是...我确信这已经在文献中完成了,所以我正在寻找参考资料。
【解决方案2】:

尝试使用二进制求幂。我的意思是做:

111 * 111 = 111^2,现在你知道 111^2 是什么,你现在可以通过 (111^2) * (111^2) 来计算 111^4。这是整个序列(请注意,这可能不是最有效的方式)。

111 * 111 = 111^2
111^2 * 111^2 = 111^4
111^4 * 111^4 = 111^8
111^8 * 111^8 = 111^16
111^16 * 111^16 = 111^32
111^32 * 111^32 = 111^64
111^64 * 111^32 = 111^96
111^96 * 111^16 = 111^112
111^112 * 111^8 = 111^120
111^120 * 111^2 * 111^1 = 111^123.

【讨论】:

  • 我相当肯定,如果这真的优化了任何东西,它就会被内置到类中。一般来说,宁愿做最简单的事情。
  • 我认为海报可能一直在创建自己的实现或其他东西。
  • 问题不在计算 111^123 而是在计算 (111^123)^(1/123) let a = 111^123 然后计算 a^(1/123),标准算法必须计算 a^122以及低于此的所有权力。这是一个问题,因为 (111^123)^122 是一个非常大的数字。请注意,BigDecimal 类没有实现根函数。
  • 使用相同的方法,但使用平方根。
  • 好吧,我真的不想计算 111^123^122.. 因为无论哪种方式,数字都太大并且会占用内存和时间。我需要一种替代方法来计算不首先计算幂的根
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2016-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多