需求背景:由於一些場景我們需要在前端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