UNPKG

@lzwme/asmd-calc

Version:

支持浮点数精度的加减乘除四则运算 JS 库。

217 lines (156 loc) 7.28 kB
[![@lzwme/asmd-calc](https://nodei.co/npm/@lzwme/asmd-calc.png)][download-url] # @lzwme/asmd-calc [![build status](https://github.com/lzwme/asmd-calc/actions/workflows/node-ci.yml/badge.svg)](https://github.com/lzwme/asmd-calc/actions/workflows/node-ci.yml) [![NPM version][npm-badge]][npm-url] [![node version][node-badge]][node-url] [![npm download][download-badge]][download-url] [![GitHub issues][issues-badge]][issues-url] [![GitHub forks][forks-badge]][forks-url] [![GitHub stars][stars-badge]][stars-url] ![license MIT](https://img.shields.io/github/license/lzwme/asmd-calc) <!-- [![minzipped size][bundlephobia-badge]][bundlephobia-url] --> 一个短小精悍的四则运算 JS 工具方法库,支持浮点数精度的加减乘除计算。 提供常见的加(`add`)、减(`sub`)、乘(`mul`)、除(`div`)计算方法,可满足涉及金额、价格处理等前端数据计算的大多数应用场景。 **为什么选用 `asmd-calc`:** - 短小精悍。仅包含加减乘除计算,核心代码不足百行,无其他依赖,文件小巧够用 - 执行性能高。仅考虑前端可精确表达的四则运算,实现逻辑简洁,执行性能优于功能丰富复杂的开源库(详见 Benchmark 部分) - 准确稳定。数个金融类交易系统多年开发实践经验的积累,覆盖了常见的各种计算用例误差场景 **不适用的情况:** - 对于涉及超大数等`前端无法精确表示的数值处理`,建议由后端语言计算并使用字符串方式返回给前端展示。也可使用 `math.js` 等开源库以字符串形式执行计算。 - 对于较为`复杂的数学科学计算`需求,推荐使用开源库如 [math.js](https://mathjs.org/index.html)、[decimal.js](https://github.com/MikeMcl/decimal.js)、[calculatorjs](https://github.com/fzred/calculatorjs)、[bignumber.js](https://github.com/MikeMcl/bignumber.js)、[big.js/](https://github.com/MikeMcl/big.js/)等,具体可分别参见其官方文档。 ## 安装 ```bash # npm npm i @lzwme/asmd-calc # yarn pnpm add @lzwme/asmd-calc # pnpm pnpm add @lzwme/asmd-calc ``` ## 用法 (USEAGE) ### 1. 使用简单的工具方法计算示例 #### es module ```js import { add } from '@lzwme/asmd-calc'; console.log(add(0.1, 0.2, 0.3)); // => 0.6 ``````js import * as calc from '@lzwme/asmd-calc'; console.log(calc.add(0.1, 0.2, 0.3)); // => 0.6 ``` #### commonjs ```js const calc = require('@lzwme/asmd-calc'); console.log(calc.add(0.1, 0.2, 0.3)); // => 0.6 ``` ### 2. 使用链式操作类计算示例 #### es module ```js import { AsmdCalc } from '@lzwme/asmd-calc'; const a = new AsmdCalc(0); console.log(+a.add(0.1).add(0.2, 0.3)); // => 0.6 const b = new AsmdCalc(0.3); b.add(0.1, 0.2).add(0.1).sub(0.1, 0.2).sub(0.1).div(0.3).mul(0.3); console.log(+b); // => 0.3 console.log(b.value); // => 0.3 ``` #### commonjs ```js const AsmdCalc = require('@lzwme/asmd-calc').AsmdCalc; const calc = new AsmdCalc(0); console.log(calc.add(0.1).add(0.2, 0.3)); // => 0.6 ``` ## API - `add(...args)` 加法运算 - `sub(...args)` 减法运算 - `mul(...args)` 乘法运算 - `div(...args)` 除法运算 - `keepDotLength(value: number | string, precision: number, type: 'ceil' | 'round' | 'fround' | 'floor' | boolean = 'floor'): number | null` 保留 N 位小数,返回数值 - `toFixed(value: number | string, precision: number, type: 'ceil' | 'round' | 'fround' | 'floor' | boolean = 'floor'): number | null` 保留 N 位小数(默认四舍五入[floor],返回字符串) - `getDecimalLen(num)` 获取指定数值的小数位长度 - `toNonExponential(num)` 将指定的浮点数转换为非科学计数法的字符串格式 ## 开发与测试 - 开发 ```bash pnpm install pnpm start ``` - 测试 ```bash # 单元测试 npm test # 基准测试 npm run benchmark ``` - 构建 ```bash npm run build ``` ## Benchmark ```bash npm run benchmark ``` 基准测试代码参见:[Benchmark](https://github.com/lzwme/asmd-calc/blob/master/benchmark/index.ts) 以下结果为在同一机器上分别执行 `10000*N` 次的耗时对比: | type/times | jsRaw | asmd-calc | mathjs | | ---------- | -------- | --------- | --------- | | add-10000 | 19.225ms | 169.535ms | 415.145ms | | sub-10000 | 16.269ms | 34.827ms | 171.263ms | | mul-10000 | 18.518ms | 51.625ms | 235.868ms | | div-10000 | 27.025ms | 79.504ms | 300.706ms | 预执行 `100_000` 次后再执行 `10000*N` 次的耗时对比: | type/times | jsRaw | asmd-calc | mathjs | | ---------- | -------- | --------- | --------- | | add-10000 | 7.768ms | 155.836ms | 362.819ms | | sub-10000 | 8.339ms | 25.147ms | 155.611ms | | mul-10000 | 9.995ms | 35.685ms | 224.357ms | | div-10000 | 15.666ms | 77.407ms | 280.322ms | ### Benchmark Details 随机数据集(测试用例): | type/times | [jsRawCalc] | [asmdCalc] | [decimal] | [mathjs] | | ---------- | ----------- | ---------- | --------- | --------- | | add-10000 | 4.973ms | 144.934ms | 192.637ms | 363.513ms | | sub-10000 | 6.971ms | 21.84ms | 65.373ms | 165.045ms | | mul-10000 | 8.45ms | 36.014ms | 107.898ms | 223.708ms | | div-10000 | 14.427ms | 64.409ms | 154.766ms | 290.645ms | 纯小数数据集: | type/times | [jsRawCalc] | [asmdCalc] | [decimal] | [mathjs] | | ---------- | ----------- | ---------- | --------- | -------- | | add-10000 | 0.248ms | 16.958ms | 30.875ms | 55.538ms | | sub-10000 | 0.462ms | 22.529ms | 32.719ms | 46.321ms | | mul-10000 | 0.232ms | 18.006ms | 34.765ms | 46.195ms | | div-10000 | 0.519ms | 17.37ms | 36.031ms | 47.271ms | 纯整数数据集: | type/times | [jsRawCalc] | [asmdCalc] | [decimal] | [mathjs] | | ---------- | ----------- | ---------- | --------- | -------- | | add-10000 | 0.172ms | 0.681ms | 10.248ms | 35.004ms | | sub-10000 | 0.816ms | 1.069ms | 12.736ms | 32.836ms | | mul-10000 | 0.178ms | 0.733ms | 13.827ms | 33.486ms | | div-10000 | 0.488ms | 0.699ms | 19.847ms | 42.217ms | ## 相关参考 - [确保前端 JavaScript 浮点数精度的四则运算方法](https://lzw.me/a/javascript-floating-point-arithmetic.html) ## License `@lzwme/asmd-calc` is released under the MIT license. 该插件由[志文工作室](https://lzw.me)开发和维护。 [stars-badge]: https://img.shields.io/github/stars/lzwme/asmd-calc.svg [stars-url]: https://github.com/lzwme/asmd-calc/stargazers [forks-badge]: https://img.shields.io/github/forks/lzwme/asmd-calc.svg [forks-url]: https://github.com/lzwme/asmd-calc/network [issues-badge]: https://img.shields.io/github/issues/lzwme/asmd-calc.svg [issues-url]: https://github.com/lzwme/asmd-calc/issues [npm-badge]: https://img.shields.io/npm/v/@lzwme/asmd-calc.svg?style=flat-square [npm-url]: https://npmjs.org/package/@lzwme/asmd-calc [node-badge]: https://img.shields.io/badge/node.js-%3E=_10.9.0-green.svg?style=flat-square [node-url]: https://nodejs.org/download/ [download-badge]: https://img.shields.io/npm/dm/@lzwme/asmd-calc.svg?style=flat-square [download-url]: https://npmjs.org/package/@lzwme/asmd-calc [bundlephobia-url]: https://bundlephobia.com/result?p=@lzwme/asmd-calc@latest [bundlephobia-badge]: https://badgen.net/bundlephobia/minzip/@lzwme/asmd-calc@latest