0.1 + 0.2 !== 0.3与IEEE754标准爱恨情仇

在IEEE754标准中,有两种显示浮点数的方法:单精度和双精度。在进行浮点运算时,单精度使用32位,而双精度使用64位。Javascript作为一门动态语言,其数字类型包含NumberBigInt两种。 但使用频次超高Nubmer类型是遵循IEEE754标准中的双精度浮点数 实现的。所以Javascript数字(整数和浮点数)的许多特性都依赖于此标准,例如令人费解的0.1 + 0.2 !== 0.3。 与许多其他编程语言不同,JavaScript 并未定义不同类型的数字数据类型,而是始终遵循国际 IEEE 754 标准,将数字存储为双精度浮点数。

IEEE754 浮点数的储存标准

在IEEE754中,一个浮点数 (Value) 其实可以这样表示:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> V a l u e = s i g n × b a s e e x p o n e n t × f r a c t i o n Value = sign \times base^{exponent} \times fraction </math>Value=sign×baseexponent×fraction

也就是浮点数的实际值 ,等于符号位(sign bit)乘以指数偏移值 (exponent bias)再乘以分数值(fraction)。

这种格式以 64 位存储数字,其中数字(分数)存储在位 0 到 51 中,指数存储在位 52 到 62 中,符号存储在位 63 中。

区域 含义
sign 符号位,正浮点数为 0,负浮点数为 1。
exponent 以 2 为底的指数位,一共 11 位,可以表示 0 ~ 2047,但为了表示负指数,需要减去一个偏移量 1023,所以实际表示范围是 -1023 ~ 1024。
fraction 这里是 IEEE 754 定义用来表示分数的,例如 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1.00100 1 2 1.001001_2 </math>1.0010012这个二进制数中,后面的 001001 就是分数。

IEEE754标准下的舍入规则

在 JavaScript 中,舍入规则是基于 IEEE 754 标准定义的。下面是 JavaScript 中的舍入规则:

  1. 向最接近的偶数舍入(Round to Nearest, Ties to Even) :当一个数需要舍入时,如果小数部分恰好为 0.5,那么结果将舍入到最接近的偶数。例如,1.5 舍入为 2,2.5 舍入为 2。
  2. 向零舍入(Round towards Zero) :当一个数需要舍入时,结果将朝着零的方向进行舍入。无论数的正负,都会直接截断小数部分。例如,1.5 舍入为 1,-1.5 舍入为 -1。
  3. 向上舍入(Round towards Positive Infinity) :当一个数需要舍入时,结果将朝着正无穷大的方向进行舍入。无论数的正负,都将向上舍入到下一个更大的数。例如,1.5 舍入为 2,-1.5 舍入为 -1。
  4. 向下舍入(Round towards Negative Infinity) :当一个数需要舍入时,结果将朝着负无穷大的方向进行舍入。无论数的正负,都将向下舍入到下一个更小的数。例如,1.5 舍入为 1,-1.5 舍入为 -2。

在 JavaScript 中,舍入规则通常由一些内置的函数来执行,例如:

  • Math.round(x):将参数 x 舍入为最接近的整数。如果小数部分恰好为 0.5,则舍入到最接近的偶数。
  • Math.floor(x):向下舍入到小于或等于 x 的最大整数。
  • Math.ceil(x):向上舍入到大于或等于 x 的最小整数。
  • Math.trunc(x):截断 x 的小数部分,返回整数部分。

这些函数根据对应的舍入规则对数字进行舍入,并返回结果。请注意,这些函数的参数和返回值都是浮点数类型。

Javascript 最大/小安全数怎么来的

在 JavaScript 中,最大安全数和最小安全数是由数据类型的表示范围所决定的。JavaScript 使用双精度浮点数表示数字,遵循 IEEE 754 标准。

最大安全数(Max Safe Integer)是 JavaScript 中能够准确表示的最大整数。它的值为 2^53 - 1,即 9007199254740991。这是因为 JavaScript 中的双精度浮点数使用 64 位来表示,其中 1 位用于符号位,11 位用于指数,剩下的 52 位用于尾数。由于指数部分需要包括正负号,因此可以表示的整数范围为 [-2^53, 2^53-1],而最大安全数是表示范围内的最大整数。

最小安全数(Min Safe Integer)是能够准确表示的最小整数,其值为 -2^53 + 1,即 -9007199254740991。

JavaScript 中超出最大安全数和最小安全数范围的整数可能会失去精度,因为它们无法以双精度浮点数的形式准确表示。此时,这些数字将被近似表示为最接近的可表示数字。

要注意的是,JavaScript 还有其他表示整数的方式,如 BigInt 类型,可以处理超出最大安全数和最小安全数范围的大整数。BigInt 类型可以表示任意精度的整数,但在进行数值计算时与常规的数字类型有所不同。

Number.EPSILON是什么鬼

Number.EPSILON 是 JavaScript 中 Number 对象的一个静态属性,它表示在 1 和大于 1 的最小浮点数之间的差值。

在 JavaScript 中,浮点数的精度有限,由于浮点数的表示方式(基于 IEEE 754 标准),相邻的浮点数之间可能存在微小的差异。Number.EPSILON 提供了一个表示这种差异的常量。

具体来说,Number.EPSILON 的值是 2 的负 52 次幂(2^-52),约为 2.220446049250313e-16。这是 JavaScript 中可靠比较浮点数相等性的推荐误差范围。

可以使用 Number.EPSILON 来比较两个浮点数是否相等,避免由于浮点数精度问题带来的意外结果。一种常见的使用方式是结合绝对值函数(Math.abs())来比较两个浮点数的差值是否小于 Number.EPSILON

下面是一个示例,展示如何使用 Number.EPSILON 进行浮点数相等性比较:

ts 复制代码
function areEqual(a, b) {
  return Math.abs(a - b) < Number.EPSILON;
}

console.log(areEqual(0.1 + 0.2, 0.3));  // true
console.log(areEqual(0.1 + 0.2, 0.3 + Number.EPSILON));  // false

在上述示例中,areEqual() 函数使用 Number.EPSILON 比较两个浮点数的差值是否小于指定的误差范围,从而判断它们是否相等。这种做法可以避免由于浮点数运算带来的舍入误差导致的不准确比较。

在32位电脑上怎么计算

IEEE 754 标准定义了浮点数的表示和运算规则,不仅适用于 32 位计算机,也适用于其他位数的计算机。下面是在 32 位计算机上执行 IEEE 754 浮点数计算的一般步骤:

  1. 确定浮点数的位分配:在 32 位计算机上,IEEE 754 单精度浮点数采用以下位分配:

    • 1 位用于表示符号(S):0 表示正数,1 表示负数。
    • 8 位用于表示指数(E):指数的偏移量为 127,即实际指数值为 E - 127。
    • 23 位用于表示尾数(M):尾数采用隐含位的形式,即小数点前默认为 1。
  2. 将浮点数转换为二进制表示:根据 IEEE 754 的规则,将浮点数转换为二进制表示,包括符号位、指数位和尾数位。

  3. 规范化浮点数:根据 IEEE 754 的规范,调整指数和尾数,使得尾数的最高位为 1,并将指数值加上偏移量。

  4. 执行浮点数运算:根据需要执行加法、减法、乘法或除法等浮点数运算操作。这些操作涉及对指数和尾数的调整、舍入和溢出等处理。

  5. 舍入结果:根据舍入规则,将运算结果舍入到指定的精度。

  6. 处理特殊情况:IEEE 754 还定义了特殊的浮点数值,如正无穷大、负无穷大和 NaN(Not a Number)。在运算过程中,需要处理这些特殊情况,并根据规定的规则进行相应的操作。

需要注意的是,具体的浮点数计算实现是由硬件和编程语言的底层支持完成的。不同的计算机体系结构和编程语言可能会有一些微小的差异,但遵循的基本原则和规则都是 IEEE 754 标准定义的。因此,无论是 32 位还是其他位数的计算机,都可以依据 IEEE 754 标准进行浮点数计算。

相关推荐
夜郎king10 分钟前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳18 分钟前
JavaScript 的宏任务和微任务
javascript
夏幻灵1 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星1 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_1 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝1 小时前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions2 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发2 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_2 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞052 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl