【问题标题】:How to compute the (C/D)th root of (A/B) with arbitrary precision for arbitrarily large integers A, B, C and D?对于任意大的整数 A、B、C 和 D,如何以任意精度计算 (A/B) 的 (C/D) 次根?
【发布时间】:2017-07-12 01:17:17
【问题描述】:

我想以 任意精度 计算 (A/B) 的某个 (C/D) 次根,用于根的十进制扩展(例如,如果所需的精度是整数 @ 987654322@,结果应包含E根的小数点后位;E可能至少等于几万;A、B、C、D为包含十位的整数成千上万的十进制数字),但我发现的所有 Javascript 数学库都将拒绝处理这些数字。
我尝试使用Decimal.js,但它的精度有限,输入的大小也有限。例如,如果我想用 1025 个有效数字计算 2 的平方根(最后一个数字可能会以某种方式四舍五入),我对 Decimal.js 使用了以下代码:

Decimal.set({ precision: 1025 });
var r2 = Decimal.pow(2, Decimal.div(1, 2)).toDP(1025).toString();
console.log(r2);  

但我明白了

Error: [DecimalError] Precision limit exceeded

是否可以使用客户端(在浏览器中工作)Javascript 来解决问题?据我所知,有一些有效的算法可以计算 百万 位的根,但我没有看到在 JS 中实现任意大数和任意精度的任何算法。有可能吗?

【问题讨论】:

  • Precision: 1025 :-o
  • 您可能希望将内部工作精度设置为高于显示的精度,计算链中每 2 或 3 次操作加 1 位数字加上 3 的缓冲区。这里将给出 Decimal.set({ precision: 1029 });跨度>
  • @LutzL:我不明白...我应该使用什么代码来获取 Decimal.js 中二的平方根的 1500 位?此外,据我了解,Decimal.js 无法处理大于 2^1024 的整数。
  • 我不知道会为您打开哪个页面,在我的版本中显示“precision number: integer, 1 to 1e+9 inclusive, Default value: 20”。你从哪里得到 2^1024?

标签: javascript algorithm math numbers


【解决方案1】:

decimal.js 中,将precision 设置为1025 会在一个数字中提供总共1025 个(尾数)十进制数字。

.toDP(1025)指小数点后的数字,或小数位,本例中尾数为1026位,因为小数点前有一位1

可以假设这些方法使用了适当增加的内部工作精度,因此输出相对于舍入是正确的。这意味着如果以更高的精度重新计算,最后一位数字可能会不同。如果您想防止这种情况发生,请将舍入模式设置为 round-down(接近零)。


power 方法以大于 1020 的精度失败的原因是内部精度超过 1025,这是以字符串形式给出的内部 LN10 常量的长度。错误是因为针对这种情况的明确测试。

对于这个库,您可以使用 1000 位结果作为牛顿法的初始点,以获得改进的结果。

my_div = document.getElementById("my_div")
Decimal.set({precision:1010});
var a = Decimal.pow(new Decimal(2), Decimal.div(1,2))
my_div.innerHTML += "initial pr=1000 : "+a.toDP(1000);
Decimal.set({precision:2500});
for(var k=1; k<=4; k++) {
  a = Decimal.div(a.add(Decimal.div(2,a)),2);
  my_div.innerHTML += "<br> Newton "+k+" : "+a;
}
<script src="https://raw.githubusercontent.com/MikeMcl/decimal.js/master/decimal.js"></script>
<div id="my_div"></div>

【讨论】:

  • 我如何使用 Decimal.js 查看 sqrt(2) 小数点后的前 1500 个小数位?我选择什么精度并不重要,但我总是在大约 1000 位数字后出现错误。此外,如何处理大于 2^1024 的数字?例如,尝试使用超过 1024 个二进制数字的 new Decimal('0b1...') 会产生错误。
  • 您不能使用精度大于约 1020 的幂函数(可能还有 exp 和 log),因为它们的代码包含“仅”提供 1025 位数字的 LN10 常量。您可以使用牛顿来细化多项式根,请参阅最后的编辑和示例。
  • 据我了解,这种方法依赖于知道幂的导数。我认为它不能应用于使用 decimal.js 的大数。
  • 你必须解决f(X)=X^D-A。它的派生词是f'(X)=A*X^(D-1)。牛顿步一如既往地X=X-f(X)/f'(X)。您需要为不依赖于提供的pow 函数的(正)整数指数实现自己的powint 过程,因为它的精度限制。减半平方算法的示例代码很容易找到。 -- 替代方法是三阶哈雷方法或(1+(A/X^D)-1)^(1/D)(1+(X^D/A-1))^(-1/D) 的幂/泰勒级数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多