编程崽

登录

一叶在编程苦海沉沦的扁舟之上,我是那只激情自射的崽

数学计算插件

数学计算插件

js一直存在一个 0.1 + 0.2 !== 0.3 的问题。

官方解答是类似js在计算时,会把数字转为二进制进行计算,而一些小数转为二进制时,是一个无尽的类似「00100000100...」的值,真正计算后再转为十进制,就会失去精度的一个说法。

反正结果就是,js不能用来直接计算小数。

所以下面这几个插件,给经济金融股票相关的页面开发者省太多头发了。

decimal.js、bignumber.js和big.js

这三个插件是同一个作者开发的,所以使用的逻辑几乎一样,区别就是适用的方面和API数量不同。

  • decimal.js:超出js安全数值范围会失去精度,大多数时适用
  • bignumber.js:超出js安全数值范围也不会失去精度,适合财务计算时使用
  • big.js:类似bignumber.js,但API方法数量比较少

这几个插件,加减乘除需要调用不同方法,虽然主要使用 加减乘除,但这个插件内部的方法还是挺多的。

安装三者的方法

三个方法,使用其中一个即可,正常可以使用decimal.js,但当进行财务计算、web3区块链、虚拟币相关时,可以使用bignumber.jsbig.js

sh 复制代码
npm install --save decimal.js

npm install --save bignumber.js

npm install --save big.js
# 如果使用ts,big.js需要手动自行安装
npm install --save-dev @types/big.js

引入

js 复制代码
// 方式一
import { Decimal } from 'decimal.js';
import { BigNumber } from 'bignumber.js';
import { Big } from 'big.js';

// 方式二
const Decimal = require('decimal.js');
const BigNumber = require('bignumber.js');
const Big = require('big.js');

使用举例

使用时,建议传数字字符串,避免当数字过大或者过小时,超过js数字安全范围,值的某些位数被替换为0。

js 复制代码
// 先声明再使用,建议传入数字字符串
let decimal = new Decimal('0.8');
// 可以直接传入科学计数法
decimal = new Decimal('1.2e+21');

decimal.toFixed() // 得到值,四舍五入,可转为原数值的字符串格式(避免被科学计数法)
decimal.toExponential() // 得到值,强制使用科学计数法表示
decimal.round(2) // 四舍五入到某一位数
decimal.plus('1.23') // 加法
decimal.minus('1.23') // 减法
decimal.times('1.23') // 乘法
decimal.div('1.23') // 除法
decimal.mod('1.23') // 取余
decimal.sqrt() // 开平方根
decimal.pow(2) // 返回原值的 n 次幂
decimal.abs() // 取绝对值
decimal.neg() // (BigNumber不支持)取负值
decimal.cmp('1.23') // (BigNumber不支持)比较大小,1: 比传入的值大,-1: 比传入的值小
decimal.equals(new Decimal('1.23')) // (BigNumber和Big不支持)是否相等 true 或 false

// 截取到固定小数位,仅 decimal.js 的写法
decimal.toDP(2, Decimal.ROUND_DOWN)
// 截取到固定小数位,仅 bignumber.js 的写法
decimal.decimalPlaces(2, BigNumber.ROUND_DOWN)
// 截取到固定小数位,big.js不支持

mathjs(不推荐)

这个插件体积比较大,查看过压缩版的js,体积还有500多k,建议使用另一 decimal.js,体积只有32k。

官方教程说,可以不进行初始化,直接使用evaluate方法,比如evaluate('0.1 + 0.7')的方式使用,但我实测,发现无法解决小数失去精度的问题,所以还是需要初始化一下。

github:https://github.com/josdejong/mathjs

使用编译工具

安装插件

sh 复制代码
npm install mathjs -S

初始化和配置插件

js 复制代码
// Math.js

// 引入插件
import { create, all } from 'mathjs';

// 初始配置
const mathjs = create(all);
mathjs.config({ number: 'BigNumber' });

// 生成方法
const computedMath = (str) => {
try {
  let num = `${mathjs.evaluate(str)}`
  return num
} catch(err) {
  // eslint-disable-next-line
  console.error('math.js中出错', err)
  return '0'
}
}

// 导出
export default computedMath;

使用方法

js 复制代码
// 使用
import computedMath from './Math.js'

// 直接把数学公式的字符串,放进去计算即可
let result = computedMath('0.1 + 0.2') // => 0.3

// 除了上面简单的加法,还可以把更复杂的公式放进去,比如 `(11 * 23 + 23) / 123 * 22` 类似的式子

// 当然这个插件也不是只有这点东西,是一个很完备功能强大的插件据说可以完全取代js中的 Math 对象,有兴趣的可以深入研究一下

使用静态HTML

使用静态html,就不能使用npm,也不能使用es6语法,那么就引入插件js。

下载此插件js:https://unpkg.com/mathjs/dist/math.min.js,然后引入:

html 复制代码
<script src="./math.min.js"></script>

初始化插件,可以暴露出一个方法到window上,或者其他调用方式都可以

js 复制代码
// 初始配置
var mathjs = math.create(math.all);
mathjs.config({ number: 'BigNumber' });

// 生成方法
window.computedMath = function(str) {
try {
  let num = String(mathjs.evaluate(str))
  return num
} catch(err) {
  console.error('math.js中出错', err)
  return '0'
}
}