javascript 中的非常大的数字

IT技术 javascript types numbers integer biginteger
2021-02-03 02:30:14

我正在研究 Project Euler 问题(目前是问题 13)。

对于这个问题,我必须找到大小与此类似的 100 个数字总和的前 10 位数字:

91,942,213,363,574,161,572,522,430,563,301,811,072,406,154,908,250

我想我可以使用 Java 的 BigInteger 之类的东西,但我开始用 JavaScript 解决问题(我正在努力提高我的 js 工作能力),我想继续使用它,甚至解决这个问题。

如果可能的话,我想坚持使用纯 JS。

5个回答

您将需要一个基于 javascript 的 BigInteger 库。有很多可供选择。这是一个https://github.com/peterolson/BigInteger.js

你可以像这样使用它

var n = bigInt("91942213363574161572522430563301811072406154908250")
    .plus("91942213363574161572522430563301811072406154908250");
我实际上能够通过将所有值直接加在一起来得出正确的答案。我之前的代码中一定有错别字。但是我已经接受了这个答案,因为它似乎是最可靠的,而且我怀疑我的简单解决方案是否适用于所有情况——可能只是侥幸。
2021-04-01 02:30:14

Javascript 最近获得了一种新的原始数据类型BigInt(截至 2020 年 1 月的第 4 阶段提案)。 https://github.com/tc39/proposal-bigint

Chrome、Firefox 和少数其他浏览器已开始在较新版本中支持此功能(在此处检查兼容性),而其他浏览器仍在实现它。

https://developers.google.com/web/updates/2018/05/bigint

基本上它可以使用任何文字来声明,例如

var a = 1n;

或者

var b = BigInt('22222222222222222222222222222222');

数学运算符不会在 BigInt 和 Number 之间进行自动转换,因此

1 + 1n

会抛出错误。

你总是可以将你的总和转换为 a string,撕掉.并获取结果 - 像这样:

var sum = 2384762348723648237462348;
sum = sum.toString(); // "2.3847623487236483e+24"

// Rip out the "."
sum = sum.substr(0, 1) + sum.substr(2);

// Grab the first 10 characters
var firstTen = sum.substr(0, 10);
@bhspencer 实际上,如果您取第一个有效的 15 位数字(IEEE754 双精度数保证准确)并总结其中的 100 个,那么 5 位数字的额外差距将使您免于不准确。至少我想不出错误可能会进一步传播的情况。
2021-03-16 02:30:14
这样做不会得到准确的答案。
2021-03-26 02:30:14
@AlexMcMillan var firstTen = sum.substr(0, 10);- 你正好是 10 位数字。要精确地添加 100 个数字,您需要有一个至少多 3 个数字的安全“缓冲区”。
2021-03-27 02:30:14
@bhspencer 根据您需要获得结果的前 10 位数字的问题。所以初始数字有多长并不重要。
2021-03-28 02:30:14
@zerkms 我们在这里没有做任何数学运算 - 假设已经完成以生成sum变量(因此名称为“sum”)。OP 只想要总和的前 10 位数字,因此返回 13 或 15 位数字只是......错误。:)
2021-04-07 02:30:14

令人惊讶的是,将所有值粘贴在一个数组中并将它们加在一起,然后只取前 10 位数字就可以了。当我的代码之前不起作用时,我一定在某处输入了拼写错误。

我敢肯定,做这么简单的事情不会在所有情况下都有效(就像@AlexMcmillan 和 @zerkms 一直在争论的那样)。我认为最安全的选择是@bhspencer 提到的 BigInteger 库,但似乎在某些情况下,将前 x 位有效数字与 y 位数字添加为缓冲区也可能值得一试。

我使用一个数组并用一个函数更新所有条目来做到这一点。

function f(a) {
  for (let i = 0; i < a.length - 1; i++) {
      a[i + 1] = a[i + 1] + parseInt(a[i] / 10);
      a[i] = a[i] % 10;
  }
  return a;
}
// remember to init the array with enough elements for all digits
var a = Array(200);
a.fill(0);
a[0] = 1;

是一个带有问题 20 代码的 JSFiddle。

Project Euler 明确声明(每次您解决问题时)您不应公开发布您的解决方案。
2021-04-14 02:30:14