vue中使用decimal.js對前端數值型別進行高精度計算

QAQhong發表於2024-09-29

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

相關文章