JavaScript `0.1+0.2 !== 0.3`,为什么?

JavaScript 0.1+0.2 !== 0.3,为什么?

分析

  • 因为在 JavaScript 中,浮点数的表示方式 导致了精度问题

  • 虽然在数学上,0.1、0.2 和 0.3 都可以精确地表示,但在计算机内部以二进制进行表示 时,它们都是无限循环小数,因此无法精确地表示。

  • 在进行浮点数运算 时,可能会出现舍入误差,导致最终结果与预期值略有偏差。

  • 比较两个浮点数,设定一个小的误差范围 来判断它们是否近似相等

  • 误差范围通常称为容差(tolerance)或者阈值(threshold),用于允许一定程度的误差。

  • JavaScript 使用 IEEE 754 标准表示浮点数 ,而这个标准在计算机内部采用二进制表示 ,因此无法精确表示一些十进制小数。例如,0.1 在二进制表示中是一个无限循环小数。

  • 为了避免这种问题,通常建议在比较浮点数 时,不要直接使用相等运算符(===) ,而是应该考虑使用误差范围内的比较 。例如,可以使用一个很小的误差范围来判断两个浮点数是否近似相等

举例

很小的误差范围来判断两个浮点数是否近似相等

  • 比较两个浮点数 a 和 b 是否近似相等
  • 避免直接使用相等运算符 造成的浮点数精度问题 ,从而更可靠地比较浮点数
js 复制代码
function approximatelyEqual(a, b, epsilon) {
  // 接受三个参数:两个浮点数 a 和 b,以及一个表示容差的值 epsilon。
  return Math.abs(a - b) < epsilon // 返回一个布尔值,表示两个浮点数是否在[容差范围内近似相等]。
}

// 比较 0.1 + 0.2 是否近似等于 0.3,设置容差为 0.000001
let result = approximatelyEqual(0.1 + 0.2, 0.3, 0.000001)

console.log(result) // true

实际项目,考虑第三方库:

小数的加法 decimal.js 或者 big.js 提供了对浮点数的高精度计算支持

工作原理

使用字符串表示浮点数 ,而不是使用 JavaScript 原生浮点数表示 方式。可以避免在转换和计算过程 中产生精度损失 ,从而得到精确的计算结果

big.js

使用 big.js 库来计算 0.1 + 0.2 的示例:

安装:

bash 复制代码
npm install big.js

使用:

js 复制代码
const Big = require('big.js')

// 将 0.1 和 0.2 分别转换为 Big 对象
const num1 = new Big('0.1')
const num2 = new Big('0.2')

// 使用 Big 对象进行加法计算
const result = num1.plus(num2)

console.log(result.toString()) // 输出 0.3

decimal.js

使用 decimal.js 库来执行精确的浮点数计算

安装:

bash 复制代码
npm install decimal.js

使用:

js 复制代码
const Decimal = require('decimal.js')

// 创建 Decimal 对象表示 0.1 和 0.2
const num1 = new Decimal('0.1')
const num2 = new Decimal('0.2')

// 使用 Decimal 对象进行加法计算
const result = num1.plus(num2)

console.log(result.toString()) // 输出 0.3

其他 JavaScript 库

其他的 JavaScript 库也提供了类似的高精度浮点数计算功能。

  1. bignumber.js 常用的 JavaScript 高精度数学库 ,用于进行精确的数字计算。提供了大整数和大浮点数 的支持,并且能够处理大数字的加减乘除等数学运算。

  2. mathjs 广泛使用的数学库 ,丰富的数学函数和运算符,包括对大数和大小数的支持。

  3. fraction.js 处理分数 的 JavaScript 库,它提供了对分数的基本运算和操作 的支持。虽然它主要用于分数的计算,但也可 以用于精确的浮点数计算。

链接

相关推荐
熊的猫6 分钟前
ES6 中 Map 和 Set
前端·javascript·vue.js·chrome·webpack·node.js·es6
乆夨(jiuze)14 分钟前
vue2.7.14 + vant + vue cli脚手架转vite启动运行问题记录
前端·javascript·vue.js
梅子酱~16 分钟前
Vue 学习随笔系列十五 -- 数组遍历方法
javascript·vue.js·学习
小浣熊喜欢揍臭臭21 分钟前
Lodash的常用方法整理
javascript·lodash
老码沉思录34 分钟前
React Native 全栈开发实战班 - 核心组件与导航
javascript·react native·react.js
老码沉思录39 分钟前
React Native 全栈开发实战班 - 导航栈定制
javascript·react native·react.js
真的很上进1 小时前
⚡️如何在 React 和 Next.js 项目里优雅的使用 Zustand
java·前端·javascript·react.js·前端框架·vue·es6
小牛itbull1 小时前
ReactPress 安装指南:从 MySQL 安装到项目启动
前端·javascript·数据库·mysql·react.js·开源·reactpress
@大迁世界1 小时前
释放 PWA 的力量:2024 年的现代Web应用|React + TypeScript 示例
前端·javascript·react.js·前端框架·ecmascript
宅博士小陈1 小时前
NodeJS的安装 npm 配置和使用 Vue-cli安装 Vue项目介绍
前端·javascript·vue.js