前端:金额高精度处理

Decimal 是什么

想必大家在用js 处理 数字的 加减乘除的时候,或许都有遇到过 精度不够 的问题,还有那些经典的面试题 0.2+0.1 !== 0.3,

至于原因,那就是 js 计算底层用的是 IEEE 754 ,精度上有限制,

那么Decimal.js 就是帮助我们解决 js中的精度失准的问题。

原理

  • 它的原理就是将数字用字符串表示,字符串在计算机中可以说是无限的。
  • 并使用基于字符串的算术运算,以避免浮点数运算中的精度丢失。它使用了一种叫做十进制浮点数算术(Decimal Floating Point Arithmetic)的算法来进行精确计算。
  • 具体来说,decimal.js库将数字表示为一个字符串,其中包含整数部分、小数部分和一些其他的元数据。它提供了一系列的方法和运算符,用于执行精确的加减乘除、取模、幂运算等操作。

精度丢失用例

javascript 复制代码
const a = 31181.82
const b = 50090.91
console.log(a+b) //81272.73000000001

Decimal 的引入 与 加减乘除

如何引入

javascript 复制代码
npm install --save decimal.js  // 安装
import Decimal from "decimal.js"  // 具体文件中引入
javascript 复制代码
// 加

let a = 1
let b = 6 
// a 与 b 可以是 任何类型,Decimal 内部会自己处理兼容
// 下面两种都可以 可以带 new 也不可以不带 new(推荐带new)
let res = new Decimal(a).add(new Decimal(b)) 
let res = Decimal(a).add(Decimal(b))


// 减

js 代码解读复制代码let a = "4"
let b = "8"
// a 与 b 可以是 任何类型,Decimal 内部会自己处理兼容
// 下面两种都可以 可以带 new 也不可以不带 new
let res = new Decimal(a).sub(new Decimal(b)) 
let res = Decimal(a).sub(Decimal(b))


// 乘

js 代码解读复制代码let a = 1
let b = 6 
// a 与 b 可以是 任何类型,Decimal 内部会自己处理兼容
// 下面两种都可以 可以带 new 也不可以不带 new
let res = new Decimal(a).mul(new Decimal(b)) 
let res = Decimal(a).mul(Decimal(b))


// 除

js 代码解读复制代码let a = 1
let b = 6 
// a 与 b 可以是 任何类型,Decimal 内部会自己处理兼容
// 下面两种都可以 可以带 new 也不可以不带 new
let res = new Decimal(a).div(new Decimal(b)) 
let res = Decimal(a).div(Decimal(b))

注意

上面的结果是 一个 Decimal 对象,你可以转换成 Number 或则 String

javascript 复制代码
let res = Decimal(a).div(Decimal(b)).toNumber()  // 结果转换成 Number
let res = Decimal(a).div(Decimal(b)).toString()  // 结果转换成 String

关于保存几位小数相关

javascript 复制代码
//查看有几位小数 (注意不计算 小数点 最后 末尾 的 0)
y = new Decimal(987000.000)
y.sd()                                   // '3' 有效位数
y.sd(true)                               // '6' 总共位数

// 保留 多少个位数 (小数位 会补0)
x = 45.6
x.toPrecision(5)                         // '45.600'

// 保留 多少位有效位数(小数位 不会补0,是计算的有效位数)
x = new Decimal(9876.5)
x.toSignificantDigits(6)                 // '9876.5' 不会补0 只是针对有效位数

// 保留几位小数 , 跟 js 中的 number 一样
toFixed
x = 3.456
// 向下取整
x.toFixed(2, Decimal.ROUND_DOWN)  // '3.45' (舍入模式 向上0 向下1 四舍五入 4,7)
// 向上取整
Decimal.ROUND_UP 

//四舍五入
ROUND_HALF_UP //(主要)

// 使用例子
let num2 = 0.2
let num3 = 0.1
let res = new Decimal(num2).add(new Decimal(num3)).toFixed(2, Decimal.ROUND_HALF_UP)
console.log(res); //返回值是字符串类型

超过 javascript 允许的数字

如果使用超过 javascript 允许的数字的值,建议传递字符串而不是数字,以避免潜在的精度损失。

javascript 复制代码
new Decimal(1.0000000000000001); // '1'
new Decimal(88259496234518.57); // '88259496234518.56'
new Decimal(99999999999999999999); // '100000000000000000000'

new Decimal(2e308); // 'Infinity'
new Decimal(1e-324); // '0'

new Decimal(0.7 + 0.1); // '0.7999999999999999'

可读性

与 JavaScript 数字一样,字符串可以包含下划线作为分隔符以提高可读性。

javascript 复制代码
x = new Decimal("2_147_483_647");

其它进制的数字

如果包含适当的前缀,则也接受二进制、十六进制或八进制表示法的字符串值。

javascript 复制代码
x = new Decimal("0xff.f"); // '255.9375'
y = new Decimal("0b10101100"); // '172'
z = x.plus(y); // '427.9375'

z.toBinary(); // '0b110101011.1111'
z.toBinary(13); // '0b1.101010111111p+8'

x = new Decimal(
  "0b1.1111111111111111111111111111111111111111111111111111p+1023"
);
// '1.7976931348623157081e+308'
相关推荐
前端大卫7 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘7 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare7 小时前
浅浅看一下设计模式
前端
Lee川7 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix7 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人7 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl7 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人8 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼8 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端