如何在 Node.js 应用程序中处理大数

这篇具有很好参考价值的文章主要介绍了如何在 Node.js 应用程序中处理大数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如何在 Node.js 应用程序中处理大数

计算机很难在不损失精度的情况下准确地表示具有很多个有效数字的数字。当你将超过 JavaScript 中最大安全整数限制的整数存储为普通整数时,它们会失去精度。

在 JavaScript 生态系统中,你可以使用 BigInt 来处理大整数。但是,你也可以使用具有类似于 BigInt 功能的第三方库。

本文将是使用 BigInt 和提供类似功能的流行库管理大数的完整指南。我们还将比较第三方库的用例、优势和劣势。

JavaScript 如何编码数字?

表示大数时精度损失的挑战并不是 JavaScript 独有的。在内部,JavaScript 使用双精度二进制浮点格式来表示数字。

双精度二进制浮点格式

双精度二进制浮点格式由 IEEE 标准 754 定义。它使用 64 位来表示带符号的浮点数。用双精度二进制浮点数表示的数由符号、尾数和指数三部分组成,如下图所示:

image.png

双精度二进制浮点格式将 64 位分配给这三部分。它使用 1 位编码符号,11 位编码偏置指数,52 位编码尾数或尾数。

下面的示例显示了十进制数 -1.7976931348623157e+308 的内部双精度二进制浮点数表示。我使用了 字符来分隔这三个部分的编码。

第一位编码符号。因为我们正在编码一个负数,所以它的值为一。如果我们编码一个正数,它的值将为零。随后的 11 位编码偏置指数,最后 52 位编码尾数:

1111111111101111111111111111111111111111111111111111111111111111

计算机只能理解二进制。因此,在存储或执行数学运算之前,JavaScript 在内部将每个数字转换为双精度二进制浮点格式,如上例所示。

然而,某些数字无法准确地用二进制表示。因此,当你将某些数字从十进制转换为二进制再转换回十进制时,它们会失去精度。

同样,JavaScript 使用固定位数对双精度二进制浮点数的不同部分进行编码。因此,在处理大整数时,你需要使用第三方库或内置的 bigint 类型。

JavaScript 中的最小和最大安全整数

由于双精度格式将表示尾数的位数限制为 53,因此你可以使用的 JavaScript 整数的精度和准确性存在限制。

你可以在不丢失精度的情况下使用的最大安全整数是 2 ** 53 - 1。它也是使用 Number.MAX_SAFE_INTEGER 访问 Number 构造函数的静态数据属性:

console.log(2 ** 53 - 1 === Number.MAX_SAFE_INTEGER) // true

还有一个对应的最小安全整数,其值为-(2**53-1)。你可以使用 Number.MIN_SAFE_INTEGER 静态属性访问它的值:

console.log(-(2 ** 53 - 1) === Number.MIN_SAFE_INTEGER) // true

你执行的任何涉及大于最大安全整数或小于最小安全整数的整数的数学运算都将导致意外的近似结果:

const maxSafeInteger = Number.MAX_SAFE_INTEGER;
const minSafeInteger = Number.MIN_SAFE_INTEGER;

console.log(maxSafeInteger + 1); // 9007199254740992
console.log(maxSafeInteger + 2); // 9007199254740992
console.log(maxSafeInteger + 1 === maxSafeInteger + 2); // true

console.log(minSafeInteger - 1); // -9007199254740992
console.log(minSafeInteger - 2); // -9007199254740992
console.log(minSafeInteger - 1 === minSafeInteger - 2); // true

JavaScript 中的正无穷大和负无穷大

就像上面的最小和最大安全整数一样,JavaScript 有一个它可以在内部表示的最大数值。该值为 2 ** 2014 - 1。你可以使用 Number.MAX_VALUE 数据属性访问它。

JavaScript 使用 Infinity 表示任何超过 Number.MAX_VALUE 的数值,并使用 -Infinity 表示相应的负值,如下例所示:

console.log(Number.MAX_VALUE * 2); // Infinity
console.log(Number.MAX_VALUE * 3); // Infinity
console.log(-Number.MAX_VALUE * 3); // -Infinity

尽管 Infinity 在 Node 中是全局的,但你可以使用 Number.POSITIVE_INFINITY 数据属性访问它,并使用 Number.NEGATIVE_INFINITY 数据属性访问 -Infinity

如何使用 BigInt 在 JavaScript 中管理大整数

正如前面部分所介绍的那样,JavaScript 在内部使用双精度格式来表示数字。因为它使用 53 位来编码尾数,所以你可以在 JavaScript 中使用的最大安全整数是 2**53 - 1

要安全地处理大于最大安全整数的整数,你需要 bigint 类型。它是在不损失精度的情况下操作大整数的内置功能。

你可以通过将 n 附加到整数或使用 BigInt 函数来创建 bigint 类型。因为 BigInt 不是构造函数,所以不使用 new 关键字调用它,如下面的示例所示:

const number = 1n;
console.log(1n + 2n); // 3n

const maxSafeInt = BigInt(Number.MAX_SAFE_INTEGER);
console.log(maxSafeInt + 1n); // 9007199254740992n
console.log(maxSafeInt + 2n); // 9007199254740993n
console.log(maxSafeInt * maxSafeInt); // 81129638414606663681390495662081n

与普通的数字类型不同,你不能将内置的 Math 方法与 BigInt 值一起使用。但是,你可以使用 bigint 类型执行基本的数学运算,例如加法减法求幂

console.log(2n + 3n) // 5n
console.log(2n - 3n)  // -1n
console.log(2n ** 3n) // 8n
console.log(4n % 3n)  // 1n
console.log(BigInt(3) - 4n) // -1n

由于你只能使用 bigint 类型执行基本的数学运算,因此在 JavaScript 中处理大量数字时,你可能需要为某些用例使用第三方库。

在 JavaScript 中管理大数的库

除了内置的 bigint 类型之外,还有几个第三方库可以在 JavaScript 中处理大数字。其中一些库附带了 BigInt 可能不提供的解决方案。

但是,与任何第三方库一样,使用它们也有缺点。它们伴随着额外的打包大小、维护、安全和许可问题。

使用 Math.js 管理大数

Math.js 是一个免费、开源且功能丰富的数学库。你既可以在浏览器中使用它,也可以在 Node 运行时环境中使用它。

虽然它是一个功能丰富的库,但在本文中,我们将使用 Math.js 在 Node 运行时环境中管理大数。用你的包管理器 npm 安装它,如下所示:

# npm 
npm i mathjs

# yarn
yarn add mathjs

#pnpm
pnpm add mathjs

安装 Math.js 后,你可以使用默认配置加载和使用它,如下例所示:

const { add, subtract, evaluate }= require('mathjs');

const sum = add(2, 3);
const difference = subtract(2, 3);
const anotherSum = evaluate('2 + 3');

console.log(sum); // 5
console.log(difference}); // -1
console.log(anotherSum}); // 5

你可以使用自定义配置创建一个 Math.js 实例,而不是使用默认配置的 Math.js 内置函数:

const { create, all } = require("mathjs");

const config = {};
const math = create(all, config);

console.log(math.add(2, 3)); // 5
console.log(math.pow(2, 3)); // 8
console.log(math.divide(4, 2)); // 2
console.log(math.multiply(2, 3)); // 6

Math.js 具有专门用于处理大数的 BigNumber 数据类型。

在上面的一个部分中,我们强调了在使用内置数字类型时,JavaScript 使用 Infinity 表示超过最大可表示数值的数字。

使用 Math.js,你可以表示超过最大可表示数的数字并对它们执行数学运算。但是,请注意,对 BigNumber 类型执行数学运算比对普通数字类型执行数学运算要慢

const { create, all } = require("mathjs");

const config = {};
const math = create(all, config);

const maxValue = math.bignumber(Number.MAX_VALUE);
console.log(math.add(maxValue, maxValue)); // 3.5953862697246314e+308

const maxSafeInt = math.bignumber(Number.MAX_SAFE_INTEGER);

console.log(math.square(maxSafeInt)); // 8.1129638414606663681390495662081e+31
console.log(math.add(maxSafeInt, maxSafeInt)); // 18014398509481982
console.log(math.subtract(maxSafeInt, maxSafeInt)); // 0
console.log(math.multiply(maxSafeInt, math.bignumber(2))); // 18014398509481982
console.log(math.divide(maxSafeInt, math.bignumber(2))); // 4503599627370495.5

console.log(math.log10(maxSafeInt)); // 15.95458977019100329811178809273377220616031325194798178472905735
console.log(math.pow(maxSafeInt, math.bignumber(2))); // 8.1129638414606663681390495662081e+31

使用 bignumber.js 管理大数

bignumber.js 是另一个用于管理任意精度十进制和非十进制数的 JavaScript 库。它是一个免费、开源、MIT 许可的库,用于处理大数据。

它可在浏览器、Node 和 Deno 中运行。要开始使用 bignumber.js,请用 npm 安装它:

# npm 
npm i bignumber.js

# yarn
yarn add bignumber.js

#pnpm
pnpm add bignumber.js

安装后,导入并创建一个 BigNumber 构造函数的实例,它以数字、字符串或 BigNumber 类型作为参数并返回一个对象。

在下面的示例中,我使用 commonjs 语法导入 bignumber.js。它还支持 ES 语法。如果你打算在没有 JavaScript 打包器的情况下在浏览器环境中使用 bignumber.js,你也可以通过 CDN 访问它:

const BigNumber = require("bignumber.js");

const distanceOfTheSun = new BigNumber('1.49597870700e11'); // 
console.log(distanceOfTheSun) // BigNumber { s: 1, e: 11, c: [ 149597870700 ] }
console.log(distanceOfTheSun.valueOf()) // 149597870700

当使用内置数字类型时,JavaScript 会将任何大于 Number.MAX_VALUE 的数值表示为 Infinity。但是,对于 bignumber.js,你可以使用任何大于 Number.MAX_VALUE 的值。

在下面的示例中,我通过将 Number.MAX_VALUE 作为字符串传递并计算其平方来创建 BigNumber 的实例。如果你使用内置的 JavaScript 数字类型做同样的事情,你会得到 Infinity

const BigNumber = require("bignumber.js");

console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MAX_VALUE ** 2) // Infinity

const maxValue = new BigNumber(Number.MAX_VALUE.toString());
const square = maxValue.exponentiatedBy("2");

console.log(square.valueOf()); // 3.23170060713109998320439596646649e+616

const squareRoot = square.squareRoot();
console.log(squareRoot.valueOf()); // 1.7976931348623157e+308
console.log(squareRoot.isEqualTo(maxValue)); // true

但是,当处理无法在 JavaScript 中表示的如此大的数字时,请使用 toStringvalueOf 方法以字符串形式访问计算结果。

toNumber 方法会将你的计算结果强制转换为 JavaScript 数字类型。你仍然会遇到上面突出显示的相同 JavaScript 大数问题。你的答案将失去精度,或者 JavaScript 会将其表示为 Infinity

虽然我们在本文中的目标是使用 bignumber.js 包来处理大数,但 bignumber.js 也可以处理相应的小数。它有几个我没有在这里突出展示的内置方法。你可以通过查看文档以了解其他内置函数。

使用 JS Big Decimal 管理大数

JS Big Decimal 是另一个可用于处理大数的 JavaScript 库。与上面的同类库不同,JS Big Decimal 的包体积小,并且功能有限。你可以使用它来管理大、小十进制数。

根据你的包管理器,使用以下命令之一从 npm 包仓库安装 JS Big Decimal:

# npm 
npm i js-big-decimal

# yarn
yarn add js-big-decimal

#pnpm
pnpm add js-big-decimal

与其他两个包一样,导入 BigDecimal 构造函数并创建一个实例,如下例所示。 BigDecimal 构造函数将数字或字符串作为参数并返回 BigDecimal 对象。

然后,你可以使用 getValue 方法以字符串形式访问数字的值。或者,如果要格式化输出,请使用 getPrettyValue

const BigDecimal = require("js-big-decimal");

const value = new BigDecimal('23');
console.log(value.add(new BigDecimal(2)).getValue())

JS Big Decimal 具有执行基本数学运算的函数,例如加法减法乘法除法。下面的代码演示了如何使用它们来处理大数据:

const BigDecimal = require("js-big-decimal");

const maxSafeInt = new BigDecimal(Number.MAX_SAFE_INTEGER.toString());
const divisor = new BigDecimal("2");

console.log(maxSafeInt.getPrettyValue()); // 9,007,199,254,740,991

const sum = maxSafeInt.add(maxSafeInt);
const quotient = maxSafeInt.divide(divisor);
const diff = maxSafeInt.subtract(quotient);
const product = quotient.multiply(divisor);

console.log(sum.getValue()); // 18014398509481982
console.log(quotient.getPrettyValue()); // 4,503,599,627,370,495.50000000
console.log(diff.getPrettyValue()); // 4,503,599,627,370,495.50000000
console.log(product.getPrettyValue()); // 9,007,199,254,740,991

比较在 JavaScript 中管理大数的库

并非所有库都是完美的。每个第三方库都有用例、优点和缺点。让我们通过对比它们的优缺点并探索 GitHub 星级和问题、包大小和 npm 下载等指标来比较上述第三方包。

GitHub stars 等指标与社交媒体点赞类似。你可以将其用作第三方库受欢迎程度的指标。然而,它并没有告诉你太多关于质量的信息。

同样,npm 下载统计数据也远非精确。根据 npm,下载计数是 tarball 文件的 HTTP 200 响应服务的数量。因此,下载计数包括构建服务器、镜像和机器人的自动下载。虽然 npm 下载计数不是库活跃用户的准确度量,但你可以使用它来对包进行比较。

Math.js bignumber.js JS Big Decimal
压缩后的包体积 187.93KB 8.09KB 3.88KB
依赖数量 9 0 0
GitHub stars 13.1k 6k 96
积极维护 Yes Yes Yes
文档 Good Good Good
许可证 Apache-2.0 MIT MIT
npm 周下载量 502,656 7,114,325 25,204

上述所有第三方库都是免费的开源库,具有许可。在这三者中,Math.js 是一个功能丰富的通用数学库,而另外两个是为管理大数字而创建的。

因此,Math.js 具有最大的 Gzipped 包大小。但是,如果你使用像 webpack 这样的打包器,它是可通过 tree-shake 优化的。 Math.js 和 bignumber.js 都带有几个用于管理大数和对它们执行数学运算的特性。

另一方面,JS Big Decimal 具有最小的包大小。但是,它的功能也最少。它只能执行基本的数学运算。

小结

JavaScript 在内部使用 64 位双精度二进制浮点格式来表示数字。它分配一位表示符号,11 位表示指数,53 位表示尾数。

JavaScript 分配固定位来表示双精度浮点数的不同部分。因此,它近似于安全整数范围之外的整数。同样,它使用 Infinity 表示大于 Number.MAX_VALUE 的数值,使用 -Infinity 表示它们对应的负值。

尽管内置的 BigInt 对于处理大于最大安全整数或小于最小安全整数的整数很有用,但它是有一定局限的,因为你只能执行基本的数学运算,例如加法减法乘法求幂。你不能将它与内置 Math 对象的方法一起使用;这样做会引发错误。

要在 JavaScript 中处理大数字而不会遇到上述限制,你需要第三方库,例如 Math.js、bignumber.js 和 JS Big Decimal。尽管大多数第三方库都有局限性,正如上面强调的那样,但它们具有轻而易举处理大数的功能。文章来源地址https://www.toymoban.com/news/detail-500612.html

到了这里,关于如何在 Node.js 应用程序中处理大数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java与Python、Node.js在人工智能和区块链应用程序开发中的比较

    背景 Java、Python和Node.js都是常用的编程语言,它们在不同领域都有广泛的应用。在人工智能和区块链应用程序开发中,这三种语言都具有各自的优势和劣势。 Java的优势 Java在企业级应用中应用广泛,这得益于其跨平台性、安全性和稳定性等特点。在人工智能和区块链应用程序

    2024年02月16日
    浏览(42)
  • 如何使用Vue.js构建桌面应用程序

    Vue.js是一个流行的JavaScript框架,可以用于构建Web应用程序。但是,Vue.js也可以用于构建桌面应用程序。本文将介绍如何使用Vue.js构建桌面应用程序,包括以下步骤: 1. 选择一个Vue.js框架:选择一个适合你的Vue.js框架。我们推荐使用Electron,因为它是最流行的桌面应用程序框架

    2024年02月15日
    浏览(42)
  • 事件驱动编程:如何在应用程序中处理用户输入和交互

    [toc] 引言 1.1. 背景介绍 随着互联网技术的快速发展,应用程序被广泛应用于人们的生活和工作中。在这些应用程序中,用户输入和交互是必不可少的组成部分。如何优雅地处理用户输入和交互,让应用程序更加符合用户的使用习惯,是摆在每个程序员面前的一个重要问题。

    2024年02月07日
    浏览(52)
  • Whisper、React 和 Node 构建语音转文本 Web 应用程序

    在本文中,我们将使用 OpenAI 的 Whisper 以及 React、Node.js 和 FFmpeg 构建一个语音转文本应用程序。该应用程序将获取用户输入,使用 OpenAI 的 Whisper API 将其合成为语音,并输出结果文本。Whisper 提供了我用过的最准确的语音到文本转录,即使对于非英语母语人士也是如此。 Ope

    2024年02月13日
    浏览(45)
  • Node.js 应用的御用品: Node.js 错误处理系统

    开发中,有些开发者会积极寻求处理错误,力求减少开发时间,但也有些人完全忽略了错误的存在。正确处理错误不仅意味着能够轻松发现和纠正错误,而且还意味着能够为大型应用程序开发出稳健的代码库。 特别是对于 Node.js 开发人员,他们有时会也发现自己使用了不那么

    2024年02月10日
    浏览(43)
  • JMeter-BeanShell预处理程序和BeanShell后置处理程序的应用

    BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,JMeter性能测试工具也充分接纳了BeanShell解释器,封装成了可配置的BeanShell前置和后置处理器,分别是 BeanShell Preprocessor(BeanShell预处理程序)和BeanShell Postprocessor(BeanShell后置处理程序),能通

    2024年04月10日
    浏览(35)
  • Vue.js + Electron 的跨平台桌面应用程序开发

    本文介绍了 Vue.js 和 Electron 的基本特点和原理,并分析了它们在桌面应用程序开发中的优势和应用场景。在基于 Vue.js 和 Electron 的桌面应用程序开发实践中,本文详细介绍了项目的搭建和配置,包括环境的准备、项目的初始化和依赖的安装等步骤。然后,本文介绍了使用 Vu

    2024年02月13日
    浏览(93)
  • uniApp开发微信小程序 异步加载外部JS应用

    由于微信小程序的限制,上线代码包不能超过 2M ,一般业务只是做界面展示与交互的话,这个大小其实完全够用的,但是当我们想要使用 echarts 这样的图表插件时,代码包很容易就超了。那么我们在不使用分包技术的情况下,也可以考虑使用 we-script 这个功能组件来实现异步

    2024年02月13日
    浏览(46)
  • Mac应用程序无法打开或文件损坏的处理方法

    大多数用户在安装 Mac 应用时,经常会遇到提示 “ XXX.app 已损坏,打不开。您应该将它移到废纸篓 ” 或 “ 打不开 XXX.app,因为它来自身份不明的开发者 ” ,如下图所示: 遇到这种情况,解决的方法很简单,步骤如下: 打开系统偏好设置界面,进入安全性与隐私 点按左下

    2024年02月10日
    浏览(51)
  • LangChain:快速构建自然语言处理应用程序的工具

    ❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博相关......)👈 (封面图由文心一格生成) LangChain 是一个用于构建端到端语言模型应用的

    2023年04月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包