登录
js一直存在一个 0.1 + 0.2 !== 0.3
的问题。
官方解答是类似js在计算时,会把数字转为二进制进行计算,而一些小数转为二进制时,是一个无尽的类似「00100000100...」的值,真正计算后再转为十进制,就会失去精度
的一个说法。
反正结果就是,js不能用来直接计算小数。
所以下面这几个插件,给经济金融股票相关的页面开发者省太多头发了。
这三个插件是同一个作者开发的,所以使用的逻辑几乎一样,区别就是适用的方面和API数量不同。
这几个插件,加减乘除需要调用不同方法,虽然主要使用 加减乘除,但这个插件内部的方法还是挺多的。
三个方法,使用其中一个即可,正常可以使用decimal.js,但当进行财务计算、web3区块链、虚拟币相关时,可以使用bignumber.js或big.js。
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
// 方式一
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。
// 先声明再使用,建议传入数字字符串
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不支持
这个插件体积比较大,查看过压缩版的js,体积还有500多k,建议使用另一 decimal.js,体积只有32k。
官方教程说,可以不进行初始化,直接使用evaluate
方法,比如evaluate('0.1 + 0.7')
的方式使用,但我实测,发现无法解决小数失去精度的问题,所以还是需要初始化一下。
github:https://github.com/josdejong/mathjs
安装插件
npm install mathjs -S
初始化和配置插件
// 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;
使用方法
// 使用
import computedMath from './Math.js'
// 直接把数学公式的字符串,放进去计算即可
let result = computedMath('0.1 + 0.2') // => 0.3
// 除了上面简单的加法,还可以把更复杂的公式放进去,比如 `(11 * 23 + 23) / 123 * 22` 类似的式子
// 当然这个插件也不是只有这点东西,是一个很完备功能强大的插件据说可以完全取代js中的 Math 对象,有兴趣的可以深入研究一下
使用静态html,就不能使用npm,也不能使用es6语法,那么就引入插件js。
下载此插件js:https://unpkg.com/mathjs/dist/math.min.js,然后引入:
<script src="./math.min.js"></script>
初始化插件,可以暴露出一个方法到window上,或者其他调用方式都可以
// 初始配置
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'
}
}