vue中使用decimal.js对前端数值类型进行高精度计算
需求背景:由于一些场景我们需要在前端JavaScript进行数值计算,且对精度要求比较严谨,而前端数值是浮点类型,直接使用计算可能会产生一系列的精度问题,常见的浮点运算问题,比如精度损失等;所以例如涉及到一些金额计算等,需要进行高精度处理。
解决方案:
(1)可以把数值计算部分逻辑交给后端接口来完成,但是需增加一次网络请求开销(比较适用于需同时请求后端接口的场景)。
(2)无需请求后端接口,数据计算部分逻辑完全由前端进行,使用一些高精度处理的第三方JS库,比如decimal.js等(这里主要介绍decimal.js库)
npm 或 yarn安装引用decimal.js库:
//npm安装
npm install --save decimal.js(低版本-v4 及以下)
或
npm install decimal.js(高版本-npm v5及以上版本中)
//yarn安装
yarn add decimal.js
//引入
//Node.js
var Decimal = require('decimal.js')
//ES6 方式
import { Decimal } from 'decimal.js'
下面是一些decimal.js【加减乘除】计算的使用案例:
methods: {
handleDecimalData() {
//加法
var a1 = 0.13
var b1 = 0.25
let c1 = new Decimal(a1).add(new Decimal(b1))
console.log("加法运算 a1 + b1 =",a1 + b1)
console.log("使用decimal.js a1 + b1 =",c1.toString())
//减法
var a2 = 1.0
var b2 = 0.99
let c2 = new Decimal(a2).sub(new Decimal(b2))
console.log("减法运算 a2 - b2 =",a2 - b2)
console.log("使用decimal.js a2 - b2 =",c2.toString())
//乘法
var a3 = 1.01
var b3 = 1.02
let c3 = new Decimal(a3).mul(new Decimal(b3))
console.log("乘法运算 a3 * b3 = ", a3 * b3)
console.log("使用decimal.js a3 * b3 = ",c3.toString())
//除法
var a4 = 0.033
var b4 = 10
let c4 = new Decimal(a4).div(new Decimal(b4))
console.log("除法运算 a4 / b4 = ", a4 / b4)
console.log("使用decimal.js a4 / b4 = ",c4.toString())
}
}
对计算结果的一些处理方法:
js//四舍五入保留2位小数
total() {
let price = new Decimal(this.itemPrice);
let quantity = new Decimal(this.quantity);
let total = price.mul(quantity);
return total.toDecimalPlaces(2,Decimal.ROUND_HALF_UP).toString();
}
//向上取整
let value = new Decimal('123.456');
let ceilValue = value.ceil();
console.log(ceilValue.toString()); // 输出 "124"
//向下取整
let value = new Decimal('123.456');
let floorValue = value.floor();
console.log(floorValue.toString()); // 输出 "123"
/*
保留小数部分的取整
如果你需要保留小数部分,可以使用 toDecimalPlaces 方法结合 rounding 参数来实现向上或向下取整。
*/
//向上取整保留2位小数
let value = new Decimal('123.456');
let ceilValue = value.toDecimalPlaces(2, Decimal.ROUND_CEIL);
console.log(ceilValue.toString()); // 输出 "123.46"
//向下取整保留2位小数
let value = new Decimal('123.456');
let floorValue = value.toDecimalPlaces(2, Decimal.ROUND_FLOOR);
console.log(floorValue.toString()); // 输出 "123.45"
/**
* 格式化数值,添加千位分隔符
* @param {具体value数值} value
* @param {保留几位小数:默认为两位小数} decimals
* @param {舍入模式:默认为四舍五入} rounding
* @returns
*/
export function formatNumber(value, decimals = 2,rounding=Decimal.ROUND_HALF_UP) {
if(typeof value==='string' && value==''){
return ''
}
if (!(value instanceof Decimal)) {
value = new Decimal(value);
}
const parts = value.toDecimalPlaces(decimals,rounding).toString().split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
}
//calcResult可以是字符串类型的数值
console.log(formatNumber(calcResult));
注意:
(1)最终计算结果最好不要转成.toNumber(),毕竟还是浮点类型,可以直接.toString()转成字符串来使用。
(2)还有这个.toFixed()这个四舍五入还是少用(有些场景结果是不对的),对于计算结果要求比较严谨的场景,还是使用decimal.js的api方法实现四舍五入等处理。
参考博文链接:https://www.cnblogs.com/morango/p/14555507.html#!comments