JavaScript(第二篇)浮点数运算精度问题,一网打尽所有相关面试题

前言

本篇文章是《面试题一网打尽》专栏的 javascript 第二篇文章,彻底解决浮点数运算精度相关的面试题目。欢迎大家关注我的这个专栏。

一、IEEE 754 标准

我们经常在文档中看到这个标准感觉是什么高深的东西,其实 IEEE 是一个组织类似公司名称,754 就是一个编号而已,所以 IEEE754 就是这个组织提出的编号为 754 的规范文档,并不是什么高深的东西,这个文档我们可以在网上查看,也可以通过下面的网盘链接获取,这个文档的全程是《二进制浮点运算的IEEE754标准》

链接: https://pan.baidu.com/s/1wuKA_jE0cyn3X9w5WlSUKw 提取码: zh6t

1.1 IEEE754 规范

javascript 中整数和浮点数都是通过双精度浮点数的格式进行存储的,遵循IEEE754规范。下图截取自 IEEE754 规范的官方 pdf 文档

js 中应用的就是 double 的那一行,就是双精度,一共 11 + 53 = 64 位。

1.2 二进制的科学计数法

无论是整数还是浮点数,在存储之前都是需要先将十进制的数字转成二进制,再表示为科学记数法表示。二进制的科学记数法就是指数的底数为 2,比如

1.0001 * 2^10

转成科学记数法之后,一定是 1. 开头的,所以在存储的时候尾数部分【0001】存在后52位,但是实际上有一个永远是 1. 的开头,所以实际上是 53 为,这也是为什么最大的安全证书是 2^53 -1。

指数部分【10】存储在指数部分使用 11位存储,最后还有一位是符号位,0 表示正数,1表示负数。

一共就是 1 + 11 + 52 = 64 位。

符号位(1位)指数位(11位)尾数位(52位)

1.3 转成二进制

(1)十进制的数字整数部分转成二进制的方法是【除二取余法】

(2)小数部分转成二进制的方法是【乘二取整法】

所以对于一个即有整数部分也有小数部分的浮点数,整数部分和小数部分就需要分开来计算,然后再合并。比如整数部分得到【1101】,小数部分得到【00101】,合并一块就是【1101.00101】然后再用科学记数法表示。

1.10100101 * 2^3

1.4 指数部分的偏移量

在存储的时候指数部分需要加上一个固定的偏移量 1023【十进制】,然后再转成二进制进行存储。

为什么需要这个偏移量,因为指数部分一共 11 位,指数位的取值范围是【 -1023 ~ 1023】

1 - 2^10 ~ 2^10 -1

即便是负指数再加上这个偏移量【1023】之后也会变成正数,这样指数部分就不用符号位来指定指数的符号了。

二、数字存储

2.1 整数

整数部分转换成二进制使用除 2 取余法,当整数可以被精确地表示为 64 位浮点数时,连续的整数值不会存在偏差,但是当整数的值太大,即大于 2^53 -1【9007199254740992】,整数转化成二进制就不止 53 位了,可能54,55位,需要截取 53 前 53 位存储。所以无法精确表示。

所以有 Number.MAX_SAFE_INTEGER 表示最大安全值,是 2^53 -1 超过这个安全值的整数,连续的整数值不能再用双精度浮点数一一对应表示了。

所有整数也都是用科学计数法存储的,比如

  1. 2^52 指数位是 52+1023的二进制形式, 小数位都是 0(因为是 2 的幂)
  2. 2^53 = 9007199254740992 二进制
  3. 能够被精确表示是指,转化成二进制后小于等于53位

对于大整数解决精度的问题,可以写个方法,通过转化成字符串的方式,模拟手工算术实现大数相加。

可以,使用Number.isInteger()判断数值是否是整数

2.2 对于浮点数

浮点数是指有小数位的数字。

浮点数转换成二进制,整数部分使用除 2 取余数,小数部分使用乘 2 取整的方法,转化成二进制101.000111....人后再把这个结果用使用科学计数法表示,1.01000111*2^2

IEEE 754标准定义了浮点数的二进制表示方法

  1. 分解:将浮点数分解为整数部分和小数部分
  2. 转换整数部分:使用➗2取余法,假如结果是 10011
  3. 转换小数部分:使用✖️2取整法,无限循环小数取所需要的精度即可,假设结果是 00101
  4. 格式化:合并整数部分和小数部分 10011.00101,用科学计数法表示为指数形式1.001100101 * 2^4,【二进制数中的最高位1,并将其左侧的所有位移到小数点右边,形成一个介于1(含)和2(不含)之间的数。这个数称为尾数(Mantissa)】【小数点左移正指数,小数点右移负指数】
  5. 编码尾数:将尾数的小数部分和整数部分(整数部分一定是1,所以常被省略)【001100101】存在后52位中
  6. 编码指数:指数【4】,以特定的偏移量表示,在IEEE 754双精度浮点数中,偏移量是1023,所以实际指数存储的是,科学计数法的指数【4】 + 1023 = 1027 ,将1027转化为二进制的形式,存在11位的指数位
  7. 加上符号位,+0、 -1

有些小数使用乘2取整方法得到的结果是无限循环的值,所以在实际存储中只能截取其中的52位,就存在精度的问题。

对于浮点数的精度问题可以先转化成整数再做除法,对于浮点数的比较可以使用Number.EPSILON,计算两个浮点数的差值是否小于这个浮点数精度。

三、面试题

3.1 说说 js 为什么会存在数字精度丢失的问题,以及如何进行解决

  1. js 中的数字类型在内存中是按照 IEEE 754 规范中双精度浮点数存储的(共 64 位),(单精度浮点数32位)
  2. IEEE 754 是《二进制浮点数规范》其中 IEEE 代表一个公司,754 是一个规范的编号
  3. 64 = 1位符号位(0 代表整数,1代表负数) + 11 位指数位(k+1) + 52 位小数位 其实是 53 位,科学计数法的第一位永远是 1,也就是有效数总是 1.xxx 的形式,所以忽略不存了)
  4. 任何数字都可以使用科学计数法表示,在存储数字时是按照以 2 为基数科学计数法存储的,一个数值使用科学计数法表示之后,后 52 位只存储科学计数法的小数部分。所以能够存储的数值在一定范围内,有些数字使用科学计数法表示小数部分超过 52 位,就会精度丢失
  5. 可以使用 BigInt 来解决大整数相加,或者手动实现一个大数相加的方法。

3.2 为什么0.1 + 0.2 不等于 0.3?

  1. 这涉及到 JavaScript 使用 IEEE 754 标准来表示浮点数,而在该标准下,某些十进制小数无法完全准确表示为二进制小数,导致精度问题。
  2. 可以把小数*10转化成整数或者,使用 Number.EPSILON 比较差值

3.3 如何解决浮点数运算精度问题?

  1. 可以使用一些技巧,比如将浮点数转换为整数进行运算,然后再转换回浮点数。另外,可以使用库如 BigNumber.js 或者使用 ECMAScript 新引入的 Number.EPSILON 进行比较。
  2. 使用 toFixed(小数位数) 、toPrecision(整数+小数的总共的位数)

3.4 解释下 JavaScript 中的 Number.EPSILON。

  1. Number.EPSILON 是 JavaScript 中表示1与大于 1 的最小浮点数之差。它可以用于比较两个浮点数是否相等,例如 Math.abs(a - b) < Number.EPSILON。

3.5 如何在 JavaScript 中判断一个数字是整数?

  1. 可以使用 Number.isInteger() 方法,例如 Number.isInteger(5) 会返回 true,而 Number.isInteger(5.5) 会返回 false。

3.6 解释下 NaN(Not a Number)在浮点数运算中的作用。

  1. 当涉及到无效的浮点数运算时,JavaScript 会返回 NaN。NaN 是一种特殊的浮点数,表示一个无效或未定义的数值。
  2. 0/0
  3. Infinity/Infinity 、Infinity - Infinity
  4. 非数学运算,比如对负数开平方根、对负数取对数等
  5. 使用未初始化的变量进行运算
  6. 当阶码(指数部分)全为1时,只要位数不全为0 就是NaN

3.7 如何比较两个浮点数是否相等?

  1. 由于浮点数精度的问题,直接使用 == 或 === 可能会导致错误的比较结果。推荐使用 Math.abs(a - b) < Number.EPSILON 这种方式来比较浮点数的相等性。希腊字母

3.8 在 JavaScript 中如何处理大数运算?

  1. 对于大数运算,可以使用第三方库如 BigNumber.js,它提供了对大整数和大浮点数的支持。
  2. 自定义大数运算函数,
  3. 接受字符串形式的大数作为参数
  4. js特别大,或者特别小的数会用指数格式展示,所以在实现大数相加的时候参数要是字符串,
  5. 用toExponential 展示数字的指数表示形式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/342683.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sublime Text 3配置 Python 开发环境

Sublime Text 3配置 Python 开发环境 一、引言二、主要内容1. 初识 Sublime Text 32. 初识 Python2. 接入 Python2.1 下载2.2 安装和使用 python2.2 环境变量配置 3. 配置 Python 开发环境4. 编写 Python 代码5. 运行 Python 代码 三、总结 一、引言 Python 是一种简洁但功能强…

记录一次数据中包含转义字符\引发的bug

后端返回给前端的数据是: { "bizObj": { "current": 1, "orders": [ ], "pages": 2, "records": [ { "from": "1d85b8a4bd33aaf99adc2e71ef02960e", …

LInux初学之路linux的磁盘分区/远程控制/以及关闭图形界面/查看个人身份

虚拟机磁盘分配 hostname -I 查看ip地址 ssh root虚拟就ip 远程连接 win10之后才有 远程控制重新启动 reboot xshell 使用&#xff08;个人和家庭版 免费去官方下载&#xff09; init 3 关闭界面 减小内存使用空间 init 5 回复图形界面 runlevel显示的是状态 此时和上…

抄代码对提升编程能力有用吗?

我毕业12年&#xff0c;做开发10年&#xff0c;一直用c语言在写程序&#xff0c;编程水平从菜&#xff0c;到能应付各种项目&#xff0c;我可以肯定告诉你&#xff0c;抄代码很有用&#xff0c;新手也只能先从抄开始。 刚开始&#xff0c;啥也不懂&#xff0c;就跟着教程&#…

简单明了,汽车级LM317系列LM317D2TR4G线性电压稳压器电源设计-参数应用方案分享

低压差线性稳压器&#xff08;LDO&#xff09;&#xff0c;是指一种具有恒定电流输出电压的装置&#xff0c;主要由输入变压器、整流器、输出变压器三部分构成&#xff0c;工业原理为将输入的交流电压经过整流、滤波后得到直流输出电压&#xff0c;再经过控制元件和开关器件将稳…

Kali Linux —— 漏洞分析工具

Cisco-torch与Global Exploiter专攻Cisco漏洞 一、Cisco 工具 Kali 有许多工具&#xff0c;比如信息收集工具、密码爆破工具等等&#xff0c;还有一些可用于攻击 Cisco 路由器的工具。Cisco-torch就是这样&#xff0c;用于大规模扫描、指纹识别和利用的工具之一。 打开终端控…

查询速度提升15倍!银联商务基于 Apache Doris 的数据平台升级实践

本文导读&#xff1a; 在长期服务广大规模商户的过程中&#xff0c;银联商务已沉淀了庞大、真实、优质的数据资产数据&#xff0c;这些数据不仅是银联商务开启新增长曲线的基础&#xff0c;更是进一步服务好商户的关键支撑。为更好提供数据服务&#xff0c;银联商务实现了从 H…

互信息法的原理详解

文章目录 互信息法&#xff08;上&#xff09;互信息是什么从信息增益角度理解互信息从变量分布一致角度理解互信息 卡方检验与离散变量的互信息法 互信息法&#xff08;上&#xff09; 尽管f_regression巧妙的构建了一个F统计量&#xff0c;并借此成功的借助假设检验来判断变…

Springboot项目Nacos做配置中心

Springboot项目Nacos做配置中心 说明安装2.Springboot整合使用Nacos3.问题处理 说明 文档参考 Nacos Spring Boot 安装 查看nacos镜像 docker search nacos 下载镜像 docker pull nacos/nacos-server启动naocs镜像 docker run --env MODEstandalone --name nacos -d -p 8…

LNG接收站消防应急照明和疏散指示系统设计 ——安科瑞 顾烊宇

前言&#xff1a; 天然气在正常压力条件下冷却到约-162℃&#xff0c;可从气态冷凝成液态&#xff0c;即液化天然气( 简称 LNG) 。LNG 接收站是接卸、储存和气化 LNG&#xff0c;再由外输管道供应气态天然气和 LNG 槽车供应液态天然气的场所&#xff0c;按工艺流程和总图布置可…

“Frontiers”系列多本期刊分区下跌,1本SCI被踢,2本SCI升为Top,还可投吗?

近期&#xff0c;2023年中科院分区正式发布&#xff0c;不少学者都很关心期刊变动情况。此次分区更新中&#xff0c;Frontiers出版社旗下的医学期刊表现让人大跌眼镜。 据汇总来看&#xff0c;32本大类医学SCI期刊中&#xff0c;Frontiers of Hormone Research直接从原来的医学…

云服务器ECS_GPU云服务器_AIGC_弹性计算-阿里云

阿里云高性能云服务器60%单实例最大性能提升&#xff0c;35Gbps内网带宽&#xff0c;网络增强&通用型云服务器、本地SSD型云服务器、大数据型云服务器、GPU异构型云服务器&#xff0c;阿里云百科aliyunbaike.com分享阿里云高性能云服务器&#xff1a; 阿里云高性能云服务器…