前端小数展示精度处理

2,588 阅读2分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

前端数字展示方式,比较常用的是格式化展示百分比展示

如果有小数的话,可能会存在精度不准的情况,如以下两种问题:

  1. 四舍五入不准
  2. 小数数位不准

四舍五入

上一篇文章前端金额格式化处理中,用toFixed()处理小数部分,会存在小数位四舍五入不准的问题

问题原因:计算机的存储长度限制

解决办法:

// 测试数据如下:
formatMoney(12.035); // 12.04 正常四舍五入
formatMoney(12.045); // 12.04 异常,应该为12.05,没有四舍五入

// 解决办法如下,可正常显示
const formatMoney = (money, symbol = "", decimals = 2) => {
  let float = (
    Math.round((parseFloat(money) + Number.EPSILON) * Math.pow(10, decimals)) /
    Math.pow(10, decimals)
  ).toFixed(decimals);
  return `${symbol} ${float}`;
};
  • Number.EPSILON:表示 1 与 Number 可表示的大于 1 的最小的浮点数之间的差值
    • 引入目的是为浮点数计算,设置一个误差范围
  • Math.pow(x, y):指数次幂,x 的 y 次幂
  • Math.round:返回一个数字四舍五入后最接近的整数(四舍五入
  • Math.ceil():返回大于或等于一个给定数字的最小整数(向上取整
  • Math.floor():返回小于或等于一个给定数字的最大整数(向下取整

参考文章

小数数位

常用场景:按照百分比展示,而且保留小数点后一位

示例:

0.199 => 19.9%;
0.2578 => 25.8%;
0.13 => 13.0%;
0.1235 => 12.4%;
0.1245 => 12.5%

0.199 * 100 = 19.900000000000002
0.2578 * 100 = 25.779999999999998

方式一:不满足只保留一位小数,有时没有小数;四舍五入精度不准

展示结果:19.9%;25.8%;13%(有问题);12.3%(有问题);12.4%(有问题)

const percentFormat = (value, decimals = 1) =>
  parseFloat((value * 100).toFixed(decimals)) + "%";

方式二:不满足只保留一位小数,有时没有小数

展示结果:19.9%;25.8%;13%(有问题);12.4%;12.5%

const percentFormat = (value, decimals = 1) =>
  Math.round(value * 1000) / 10 + "%";

方式三:保留一位小数,四舍五入(暂无问题

展示结果:19.9%;25.8%;13.0%;12.4%;12.5%;

const percentFormat = (value, decimals = 1) =>
  (Math.round(value * 1000) / 10).toFixed(decimals) + "%";

方式四:保留一位小数,四舍五入(暂无问题

展示结果:19.9%;25.8%;13.0%;12.4%;12.5%;

const percentFormat = (value, decimals = 1) =>
  // 借用上面的函数处理
  formatMoney(value * 100, "", decimals) + "%";