Skip to content

JavaScript中的浮点数精度问题 🔢 ​

问题现象 ❓ ​

在JavaScript中进行浮点数运算时,经常会遇到一些令人困惑的结果:

javascript
console.log(0.1 + 0.2 === 0.3)  // false
console.log(0.1 + 0.2)          // 0.30000000000000004
console.log(0.5 - 0.4 === 0.1)  // false

原因分析 🔍 ​

  1. JavaScript中的所有数字都遵循 IEEE 754 标准,使用64位双精度浮点数存储
  2. 计算机使用二进制存储数字,某些十进制小数在转换为二进制时会出现无限循环

二进制转换示例 📝 ​

javascript
// 0.125的二进制转换过程
0.125 * 2 = 0.25  // 取整数部分: 0
0.25 * 2 = 0.5   // 取整数部分: 0
0.5 * 2 = 1.0    // 取整数部分: 1
// 最终结果: 0.125(十进制) = 0.001(二进制)

// 0.2的二进制转换过程
0.2 * 2 = 0.4    // 取整数部分: 0
0.4 * 2 = 0.8    // 取整数部分: 0
0.8 * 2 = 1.6    // 取整数部分: 1
0.6 * 2 = 1.2    // 取整数部分: 1
0.2 * 2 = 0.4    // 取整数部分: 0
// 循环继续...最终是无限循环的 0.001100110011...(二进制)

解决方案 💡 ​

  1. 使用toFixed()进行四舍五入
javascript
(0.1 + 0.2).toFixed(2) === '0.30'  // true
  1. 乘以倍数转为整数运算
javascript
(0.1 * 10 + 0.2 * 10) / 10 === 0.3  // true
  1. 使用专业的数学库
javascript
import Decimal from 'decimal.js';
new Decimal(0.1).plus(0.2).equals(0.3)  // true

最佳实践建议 ✨ ​

  1. 金融计算必须使用专业的数学库
  2. 展示金额时,始终使用toFixed()固定小数位数
  3. 对精度要求不高的场景,可以使用Math.round()或toFixed()适当处理

注意事项 ⚠️ ​

  • 不要直接比较浮点数是否相等
  • 需要精确计算时,将数值转换为整数后再进行计算
  • 展示货币金额时,推荐使用专业的格式化库,如Intl.NumberFormat
javascript
// 货币格式化示例
const formatter = new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'CNY'
});
console.log(formatter.format(0.1 + 0.2));  // ¥0.30

希望这篇优化后的博客对你有帮助!🎉