当前位置: 首页 > news >正文

理解js的精度问题

参考博客:js精度丢失问题-看这篇文章就够了(通俗易懂)、探寻 JavaScript 精度问题以及解决方案、JavaScript 浮点数陷阱及解法

1 为什么

JavaScript 中所有数字包括整数和小数都只有一种类型 即 Number类型,它的实现遵循 IEEE 754 标准

在这里插入图片描述

  • 符号位S:0代表正数,1代表负数
  • 指数位E:存储指数,用来表示次方数
  • 尾数位M:存储尾数,超出的部分自动进1舍0

计算方法:
在这里插入图片描述

因为存储时有位数限制(64位),并且某些十进制的浮点数在转换为二进制数时会出现无限循环,会造成二进制的舍入操作(0舍1入),当再转换为十进制时就造成了计算误差。

了解了存储方法之后,再以0.1来解释一下浮点误差的问题。

将十进制小数 0.1 转为二进制:

0.1 * 2 = 0.2
0.2 * 2 = 0.4 // 循环
0.4 * 2 = 0.8
0.8 * 2 = 1.6
0.6 * 2 = 1.2
0.2 * 2 = 0.4 // 循环
0.4 * 2 = 0.8
0.8 * 2 = 1.6
0.6 * 2 = 1.2
...

可以发现有限十进制小数 0.1 被转化成了无限二进制小数 0.00011001100...(0011循环),表示为科学记数法为1.100110011001100...x2^-4,所以 E=-4+1023=1019M=100110011...。由于计算机存储的长度又是有限的,所以在一定长度后会进行舍入操作,如图所示,尾数部分存在进位,精度就丢失了。

在这里插入图片描述

再从计算机中取出来的二进制数,是被进位处理过的,转化成十进制后为 0.100000000000000005551115123126,因此就出现了浮点误差。

计算机存储一个27.5的数字

  • 首先把这个数字转换为二进制 11011.1
  • 再把二进制转换为科学记数法 1.10111∗2^4
  • 又因js存储数字用的是双精度浮点数【最多存储64位】 即 符号位【1】+指数位【4+1023(固定偏移量)=> 10000000011】+小数部分【10111(52位不够用0补齐)】
  • 0100 0000 0011 1011 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

最大安全数的由来:

  • 2位 ===> 2^2=4种组合 ===> 表示的最大十进制整数2^2-1=3

  • 精度位53位 ===> 2^53种组合 ===> 表示的最大十进制整数2^53-1=9007199254740991

能被转化为有限二进制小数的十进制小数的最后一位必然以 5 结尾(因为只有 0.5 * 2 才能变为整数)。所以十进制中一位小数 0.1 ~ 0.9 当中除了 0.5 之外的值在转化成二进制的过程中都丢失了精度。

2 业务场景

场景一:大数危机

比如有个订单号后端定义的是 long 类型,但是当这个订单号转换成 JavaScript 的 Number 类型时候精度会丢失。

preview:

img

response:

img

preview中的值是错误的,response中的值是正确的,postman中请求的值跟response是一致的,那说明问题就出现在浏览器中。

查阅资料知道,在preview中,控制台会把发送过来的json数据自动转换成javascript的对象格式,而js的Number类型并不能完全表示Long型的数字,当它超过最大安全数(Math.pow(2, 53) - 1,即 9007199254740991)时,就可能会发生精度丢失的问题。

解决方法:

方案一:在返回数据之前就将数据转换为字符串。
方案二:在传递给 then/catch 前,结合开源库json-bigint,使用transformResponse修改响应数据。

import JSONBig from 'json-bigint';const res = await axios({url: requestUrl,params: queryStringParameters,data,method,transformResponse: [function (resData) {try {return JSONBig.parse(resData);} catch (e) {return JSON.parse(resData);}},],
});

另外一个情况,如果我门需要使用大于最大安全数的整数,则可以考虑使用BigInt数据类型,它可以表示大于 2^53 - 1 的整数。

9007199254740991+2 // 90071992547409929007199254740991n+2n // 9007199254740993n

场景二:浮点数的加减乘除

比如涉及费用计算的时候,可能会存在小数相乘的情况。如下图,1222.1*100000应该等于的是122210000,但js乘出来的结果却是122209999.99999999,这也是因为精度丢失导致的。

在这里插入图片描述
在这里插入图片描述

解决方法:

方案一:扩大缩小法,将小数转换成字符串,记录小数点后面的位数的长度,再转换成整数相乘,最后除以扩大倍数。

function twoNumberMulti(multiplicand, multiplier) {let m = 0;const multiplicandStr = String(multiplicand);const multiplierStr = String(multiplier);if (multiplierStr.includes('.')) {m += multiplierStr?.split('.')[1]?.length || 0;}if (multiplicandStr.includes('.')) {m += multiplicandStr?.split('.')[1]?.length || 0;}return (Number(multiplicandStr.replace('.', '')) * Number(multiplierStr.replace('.', ''))) / 10 ** m;
}console.log(twoNumberMulti(1222.1,100000)) // 122210000

方案二:开源库number-precision,将小数转为整数后再作处理,支持浮点数的加减乘除、四舍五入等运算。

相关文章:

理解js的精度问题

参考博客:js精度丢失问题-看这篇文章就够了(通俗易懂)、探寻 JavaScript 精度问题以及解决方案、JavaScript 浮点数陷阱及解法 1 为什么 JavaScript 中所有数字包括整数和小数都只有一种类型 即 Number类型,它的实现遵循 IEEE 754 标准。 符号位S&#…...

蓝桥杯 时间显示

题目 输入输出样例 示例 1 输入 46800999输出 13:00:00示例 2 输入 1618708103123输出 01:08:23评测用例规模与约定 对于所有评测用例,给定的时间为不超过 10^{18}1018 的正整数。 运行限制 最大运行时间:1s最大运行内存: 512M 基础知识 时间的转换…...

qt中设置菜单高度

如题所示,我建立一个菜单,代码如下,但是菜单项的高度太小了, { popupMenu new QMenu(this); QAction *action1 new QAction(tr(“&New1”), this); QAction *action2 new QAction(tr(“&New2”), this); QA…...

测开:前端基础-css页面布局-定位

一 、传统网页布局的三种方式 网页布局的本质–用CSS来摆放盒子,把盒子摆放到相应的位置,css提供了三种传统布局方式,分别是标准流,浮动和定位三种。 二、 定位 2.1 啥是定位 我的理解,就是要把这个元素&#xff0c…...

Servlet中八个监听器介绍

一、监听对象创建的监听器 1、ServletContextListener /*** 用于监听ServletContext对象创建和销毁的监听器* since v 2.3*/public interface ServletContextListener extends EventListener {/*** 对象创建时执行此方法。该方法的参数是ServletContextEvent事件对象&#xf…...

LicenseBox Crack,对服务器的要求最低

LicenseBox Crack,对服务器的要求最低 LicenseBox是用于管理基于PHP的软件、WordPress插件或主题、主题、插件和WordPress的更新和许可的完整软件。它易于安装,对服务器的要求最低,用户友好的界面,无限脚本的使用为您的创造力打开了大门。 Li…...

css中重难点整理(vertical-align)

一、vertical-align 在学习vertical-align的时候,可能会很困惑。即使网上有一大推文章讲veitical-align,感觉看完好像懂了,等自己布局的时候用到vertical-align的时候好像对它又很陌生。这就是我在布局的时候遇到的问题。 本来vertical-align就很不好理…...

javaScript基础面试题 ---宏任务微任务

宏任务微任务一、为什么JS是单线程语言?二、JS是单线程,怎样执行异步代码?1、JS是单线程语言 2、JS代码执行流程,同步执行完,再进行事件循环(微任务、宏任务) 3、清空所有的微任务,再…...

基于JSP的网上书城

技术:Java、JSP等摘要:随着科技的迅速发展,计算机技术已应用到社会的各个领域。随着计算机技术和通信技术的迅速发展,网络的规模也逐渐增大,网络的元素也随之不断增加,有的利用其通信,有的利用其…...

C#教程 05 常量

文章目录 C# 常量整数常量浮点常量字符常量字符串常量定义常量C# 常量 常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。 常量可以被当作常规的变量,只是它们的值在定义后不能被修改。 整数…...

【华为OD机试真题java、python】基站维修工程师【2022 Q4 100分】(100%通过)

代码请进行一定修改后使用,本代码保证100%通过率。本文章提供java、python两种代码 题目描述 小王是一名基站维护工程师,负责某区域的基站维护。 某地方有 n 个基站( 1<n<10 ),已知各基站之间的距离 s( 0<s<500 ), 并且基站 x 到基站 y 的距离,与基站 y …...

你是真的“C”——为冒泡排序升级赋能!

你是真的“C”——为冒泡排序升级赋能&#xff01;&#x1f60e;前言&#x1f64c;冒泡排序升级赋能之境界一&#xff01;冒泡排序升级赋能之境界二&#xff01;qsort库函数的运用和认识总结撒花&#x1f49e;&#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的…...

【JavaEE】基于mysql与servlet自制简易的表白墙程序

文章目录1 表白墙页面构建2 Servlet 回顾3 表白墙后端程序实现3.1 我们需要做什么&#xff1f;3.2 实现细节4 实现结果写在最后1 表白墙页面构建 该页面由标题、文本、三个 input 输入框与一个提交按钮构成&#xff0c;整体比较简单&#xff0c;相关样式文件和页面代码会在后面…...

抓包技术(浏览器APP小程序PC应用)

P1 抓包工具 01. Fidder 首先第一个Fiddler它的优势&#xff0c;独立运行&#xff0c;第二个支持移动设备&#xff08;是否能抓移动APP的包&#xff0c;&#xff09;在这一块的话wireshark、httpwatch就不支持&#xff0c;因此在这一块就可以排除掉前连个&#xff0c;因为我们…...

linux笔记(10):ubuntu环境下,基于SDL2运行lvgl+ffmpeg播放mp4

文章目录1.ubuntu安装ffmpeg1.1 源码安装1.1 克隆ffmpeg源码1.2 配置编译条件&#xff0c;编译&#xff0c;安装1.2 直接安装依赖包2.下载lvgl源码2.1 测试原始代码2.2 运行lv_example_ffmpeg_2()例程2.2.1 配置 LV_USE_FFMPEG 为 12.2.2 lv_example_ffmpeg_2()替换lv_demo_wid…...

JavaScript专题之类型判断(下)

参考原文&#xff1a;JavaScript专题之类型判断(下) 前言 在上篇《JavaScript专题之类型判断(上)》中&#xff0c;我们抄袭 jQuery 写了一个 type 函数&#xff0c;可以检测出常见的数据类型&#xff0c;然而在开发中还有更加复杂的判断&#xff0c;比如 plainObject、空对象…...

【VC 7/8】vCenter Server 基于文件的备份和还原Ⅲ—— 使用 SMB 协议备份 VC(VAMI 中文)

目录2.2 使用 SMB 协议备份 VC&#xff08;VAMI 中文&#xff09;&#xff08;1&#xff09;登录 vCenter Server 管理界面&#xff08;2&#xff09;进入备份页面&#xff08;3&#xff09;配置 Backup Schedule&#xff08;4&#xff09;开始备份&#xff08;5&#xff09;备…...

linux - 内核编译

一. 编译的实质基于头文件和c文件--->产生对象文件(.o)将所有的对象文件链接起来&#xff0c;产生可执行文件。内核的编译系统组成Makefile分布在内核源代码中的Makefile&#xff0c; 定义内核的编译规则&#xff0c;配合Kconfig使用。Kconfig配置文件&#xff0c;给用户提供…...

Spring——配置文件实现IOC和DI入门案例

现在先如图创建如下的Maven项目&#xff0c;在业务层和数据层分别写上对应的接口和实现类 在BookServiceImpl中创建一个BookDaoImpl对象&#xff0c;并调用里面的save()方法。 在测试类里面new一个bookservice的实现类&#xff0c;调用save()方法 输出如下图所示 要使用IOC容…...

机器学习100天(四十一):041 对偶支持向量机-公式推导

《机器学习100天》完整目录:目录 机器学习 100 天,今天讲的是:对偶支持向量机-公式推导! 本节主要延续上一节的内容,推导线性支持向量机的对偶形式。本节内容包含的数学理论和推导很多,我尽量简化其中的数学部分,只做感性的介绍,便于大家在理解的同时不受数学复杂公式…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...