【问题标题】:Extremely large numbers in javascriptjavascript中的非常大的数字
【发布时间】:2015-08-21 02:22:33
【问题描述】:

我正在处理 Project Euler 问题(目前为 question 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。

【问题讨论】:

  • 也许只有我一个人,但我会在 Python 中解决这个问题,它有原生的 bignums 并且比 Java 更容易使用;然后我会选择一个比这个更“Javascripty”的挑战,比如使用 HTML5 画布元素进行绘图。
  • 您可以将数字保留为数字数组,然后只需编写函数以这种方式进行数学运算(您在小学学习数学的老式方法)。

标签: javascript types numbers integer biginteger


【解决方案1】:

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

Chrome、Firefox 和其他少数浏览器已开始在较新版本 (check compatibility here) 中支持此功能,而其他浏览器仍在实施。

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

基本上它可以使用像

这样的文字来声明

var a = 1n;

或

var b = BigInt('22222222222222222222222222222222');

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

1 + 1n

会抛出错误。

【讨论】:

    【解决方案2】:

    我使用一个数组并使用一个函数更新所有条目。

    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;
    

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

    【讨论】:

    • Project Euler 明确声明(每次您解决问题时)您不应公开发布您的解决方案。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      您始终可以将总和转换为 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 位数字间隙将使您免于不准确。至少我想不出错误可能会进一步传播的情况。
      • @bhspencer 根据您需要获得结果的前 10 位数字的问题。所以初始数字有多长并不重要。
      • @AlexMcMillan var firstTen = sum.substr(0, 10); - 你正好取 10 位数。要精确添加 100 个数字,您需要有一个至少多 3 个数字的安全“缓冲区”。
      • @zerkms 我们在这里没有做任何数学运算——假设已经完成了生成sum 变量(因此名称为“sum”)。而 OP 只想要总和的前 10 位数字,所以返回 13 或 15 位数字只是......错误。 :)
      【解决方案5】:

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

      你可以这样使用它

      var n = bigInt("91942213363574161572522430563301811072406154908250")
          .plus("91942213363574161572522430563301811072406154908250");
      

      【讨论】:

      • 我实际上能够通过直接将所有值加在一起来得出正确的答案。我之前的代码中一定有错字。但我接受了这个答案,因为它似乎最可靠,而且我怀疑我的简单解决方案是否适用于所有情况——可能只是侥幸。
      猜你喜欢
      • 2023-02-16
      • 1970-01-01
      • 2014-08-12
      • 2014-01-06
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多