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

【JavaScript】浮点数精度问题

✨ 专栏介绍

在现代Web开发中,JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性,还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言,JavaScript具有广泛的应用场景,并且不断发展演进。在本专栏中,我们将深入学习JavaScript语言的基本语法、DOM操作、事件处理、异步编程以及常见算法和数据结构等内容。此外,我们还将介绍ES6及其后续版本中引入的新特性,如箭头函数、模块化、解构赋值等。通过学习这些内容,你将能够成为一名熟练的JavaScript开发者,并能够应用这些知识来构建出高质量和可维护的Web应用程序。让我们一起开始JavaScript之旅吧!

在这里插入图片描述

文章目录

    • ✨ 专栏介绍
    • 引言
    • 常见浮点数精度问题
        • 示例一:浮点值运算结果
        • 示例二:小数乘以10的n次方取整(比如:元转分,米转厘米)
        • 示例三:四舍五入保留 *n* 位小数
    • 为什么会出现这样的结果
      • 浮点数表示
      • 举例说明
        • 示例一
        • 示例二
        • 示例三
    • 前端数学库
    • 总结
    • 😶 写在结尾
        • `前端设计模式专栏`
        • `Vue专栏`
        • `JavaScript(ES6)专栏`


引言

浮点数精度问题是指在计算机中使用二进制表示浮点数时,由于二进制无法精确表示某些十进制小数,导致计算结果可能存在舍入误差或不精确的情况。

这个问题主要源于浮点数的存储方式。在计算机中,浮点数通常使用IEEE 754标准来表示。该标准将浮点数分为符号位、指数位和尾数位,使用科学计数法来表示一个浮点数。

在这里插入图片描述

常见浮点数精度问题

示例一:浮点值运算结果
// 加法 
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.7 + 0.1); // 0.7999999999999999
console.log(0.2 + 0.4); // 0.6000000000000001
console.log(2.22 + 0.1); // 2.3200000000000003// 减法
console.log(1.5 - 1.2); // 0.30000000000000004
console.log(0.3 - 0.2); // 0.09999999999999998// 乘法 
console.log(19.9 * 100); // 1989.9999999999998
console.log(19.9 * 10 * 10); // 1990
console.log(9.7 * 100); // 969.9999999999999
console.log(39.7 * 100); // 3970.0000000000005// 除法 
console.log(0.3 / 0.1); // 2.9999999999999996
console.log(0.69 / 10); // 0.06899999999999999
示例二:小数乘以10的n次方取整(比如:元转分,米转厘米)
console.log(parseInt(0.58 * 100, 10)); // 57

在上面的例子中,我们得出的结果是 57,而不是预期结果 58

示例三:四舍五入保留 n 位小数

例如我们会写出 (number).toFixed(2),但是看下面的例子:

console.log((1.335).toFixed(2)); // 1.33

在上面的例子中,我们得出的结果是 1.33,而不是预期结果 1.34

为什么会出现这样的结果

浮点数表示

在计算机中,浮点数通常使用IEEE 754标准来表示。该标准将浮点数分为符号位、指数位和尾数位,使用科学计数法来表示一个浮点数。

该规范定义了浮点数的格式,对于 64 位的浮点数在内存中的表示,最高的 1 位是符号位,接着的 11 位是指数,剩下的 52 位为有效数字,具体表示方式如下:

  • 符号位 S:用于表示正负号。第 1 位是正负数符号位(sign),0 代表正数,1 代表负数。
  • 指数位 E:用于表示浮点数的指数部分,以二进制补码形式存储。中间的 11 位存储指数(exponent),用来表示次方数。
  • 尾数位 M:用于表示浮点数的有效数字部分,以二进制形式存储。最后的 52 位是尾数(mantissa),储存小数部分,超出的部分自动进一舍零。

即:浮点数最终在运算的时候实际上是一个符合该标准的二进制数

符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。

IEEE 754 规定,有效数字第一位默认总是 1,不保存在 64 位浮点数之中。也就是说,有效数字总是 1.xx…xx 的形式,其中 xx…xx 的部分保存在 64 位浮点数之中,最长可能为 52 位。因此,JavaScript 提供的有效数字最长为 53 个二进制位(64 位浮点的后 52 位 + 有效数字第一位的 1)。

既然限定位数,必然有截断的可能。

举例说明

示例一
console.log(0.1 + 0.2); // 0.30000000000000004

为了验证该例子,我们得先知道怎么将浮点数转换为二进制,整数我们可以用除 2 取余的方式,小数我们则可以用乘 2 取整的方式。

*0.1* 转换为二进制

0.1 * 2,值为 0.2,小数部分 0.2,整数部分 0

0.2 * 2,值为 0.4,小数部分 0.4,整数部分 0

0.4 * 2,值为 0.8,小数部分 0.8,整数部分 0

0.8 * 2,值为 1.6,小数部分 0.6,整数部分 1

0.6 * 2,值为 1.2,小数部分 0.2,整数部分 1

0.2 * 2,值为 0.4,小数部分 0.4,整数部分 0

0.2 开始循环

*0.2* 转换为二进制

可以直接参考上述,肯定最后也是一个循环的情况

所以最终我们能得到两个循环的二进制数:

0.1:0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1100 …

0.2:0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 …

这两个的和的二进制就是:

sum:0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 …

最终我们只能得到和的近似值(按照 IEEE 754 标准保留 52 位,按 01 入来取值),然后转换为十进制数变成:

sum ≈ 0.30000000000000004

示例二
console.log((1.335).toFixed(2)); // 1.33

因为 1.335 其实是 1.33499999999999996447286321199toFixed 虽然是四舍五入,但是是对 1.33499999999999996447286321199 进行四五入,所以得出 1.33

示例三

Javascript 中,整数精度同样存在问题,先来看看问题:

console.log(19571992547450991) // 19571992547450990
console.log(19571992547450991 === 19571992547450992) // true

同样的原因,在 JavaScriptnumber 类型统一按浮点数处理,整数是按最大 54 位来算。

  • 最大( 253 - 1Number.MAX_SAFE_INTEGER9007199254740991)
  • 最小( -(253 - 1)Number.MIN_SAFE_INTEGER-9007199254740991)

在浮点数计算中,有一些特定的小数情况可以避免舍入误差。这是因为这些特定的小数可以精确地表示为二进制分数,而不会导致舍入误差。以下是一些常见的特定情况:

  1. 小数部分是2的负整数次幂:例如,0.5、0.25、0.125等。这些小数在二进制中可以精确表示,因此计算时不会出现舍入误差。
  2. 小数部分是10的负整数次幂:例如,0.1、0.01、0.001等。尽管在十进制中无法精确表示,但在二进制中可以通过有限位数进行近似表示,并且通常不会引起明显的舍入误差。

前端数学库

Math.js、Decimal.js和Big.js都是用于处理精确计算的JavaScript库。它们提供了更高精度的数学运算功能,解决了JavaScript中浮点数精度问题。

Math.js

Math.js是一个功能强大的数学库,提供了丰富的数学函数和运算符,以及矩阵、统计、线性代数等功能。它支持高精度计算,并提供了大整数和有理数的支持。Math.js还具有表达式解析和求值功能,可以处理复杂的数学表达式。

Decimal.js

Decimal.js是一个专门用于高精度浮点数计算的JavaScript库。它通过使用字符串来表示数字,避免了浮点数舍入误差。Decimal.js支持基本的四则运算、比较、取模等操作,并提供了各种格式化选项和精度控制。

Big.js

Big.js是另一个用于高精度计算的JavaScript库。它也使用字符串来表示数字,并提供了大整数和大浮点数的支持。Big.js支持基本运算符、比较操作、取模运算等,并具有可配置的舍入模式和格式化选项。

这些库都可以帮助开发人员在需要进行精确计算或处理大数字时避免浮点数精度问题。根据具体需求,可以选择适合自己项目的库来进行高精度计算。

需要注意的是,使用这些库可能会带来一些性能上的开销,因为高精度计算需要更多的计算资源。因此,在实际应用中,需要根据具体情况权衡精度和性能之间的平衡。

总结

浮点数精度问题是计算机科学中一个常见的问题,由于二进制无法精确表示某些十进制小数,进行浮点数运算时可能会出现舍入误差。为了解决这个问题,可以使用整数进行计算、使用专门的库或者比较时使用误差范围。了解浮点数精度问题对于开发人员在处理浮点数运算时具有重要意义。


😶 写在结尾

前端设计模式专栏

在这里插入图片描述
设计模式是软件开发中不可或缺的一部分,它们帮助我们解决了许多常见问题,并提供了一种优雅而可靠的方式来构建应用程序。在本专栏中,我们介绍了所有的前端设计模式,包括观察者模式、单例模式、策略模式等等。通过学习这些设计模式,并将其应用于实际项目中,我们可以提高代码的可维护性、可扩展性和可重用性。希望这个专栏能够帮助你在前端开发中更好地应用设计模式,写出高质量的代码。点击订阅前端设计模式专栏

Vue专栏

在这里插入图片描述

Vue.js是一款流行的JavaScript框架,用于构建用户界面。它采用了MVVM(Model-View-ViewModel)的架构模式,通过数据驱动和组件化的方式,使开发者能够更轻松地构建交互性强、可复用的Web应用程序。在这个专栏中,我们将深入探讨Vue.js的核心概念、组件开发、状态管理、路由和性能优化等方面的知识。我们将学习如何使用Vue.js构建响应式的用户界面,并探索其强大的生态系统,如Vue Router和Vuex、Pinia。通过学习这些内容,你将能够成为一名熟练的Vue.js开发者,并能够应用这些知识来构建复杂而高效的Web应用程序。点击订阅Vue专栏

JavaScript(ES6)专栏

在这里插入图片描述

JavaScript是一种广泛应用于网页开发和后端开发的脚本语言。它具有动态性、灵活性和易学性的特点,是构建现代Web应用程序的重要工具之一。在这个专栏中,我们将深入探讨JavaScript语言的基本语法、DOM操作、事件处理、异步编程以及常见算法和数据结构等内容。此外,我们还将介绍ES6(ECMAScript 2015)及其后续版本中引入的新特性,如箭头函数、模块化、解构赋值等。通过学习这些内容,你将能够成为一名熟练的JavaScript开发者,并能够应用这些知识来构建出高质量和可维护的Web应用程序。点击订阅JavaScript(ES6)专栏

相关文章:

【JavaScript】浮点数精度问题

✨ 专栏介绍 在现代Web开发中,JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性,还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言,JavaScript具有广泛的应用场景&#x…...

使用axios发送get和post请求

使用axios发送get和post请求的方法如下: 1.发送GET请求: axios.get(url).then(response > {// 请求成功的处理逻辑console.log(response.data);}).catch(error > {// 请求失败的处理逻辑console.error(error);});2.发送POST请求: ax…...

【基于VirtualBox及openEuler20.03 TLS SP1编译openGauss2.1.0源码】

【openEuler 20.03 TLS编译openGauss2.1.0源码】 一、安装环境二、安装步骤 一、安装环境 项目Value虚拟机virtualbox操作系统openEuler 20.03 TLSopenGauss2.1.0openGauss-third_party2.1.0 二、安装步骤 以下操作需要在root用户下执行 编辑/etc/selinux/config vim /etc/s…...

hibernate 使用注解+拦截器实现自动开启、关闭session,提交、回滚事务

hibernate 使用注解+注解拦截器实现自动开启、关闭session,开启、提交、回滚事务 项目为springboot项目 ,springboot版本为:2.5.11, hiernate-core5.4.3 版本。spring-xxx 等为5.3.17版本 注意:在spring-xxx4.x版本+ hiernate-core5.x.x版本中,hibernate的配置 true是有效的…...

Solidworks学习笔记

本内容为solidworks的学习笔记,根据自己的理解进行记录,部分可能不正确,请自行判断。 学习视频参考:【SolidWorks2018视频教程 SW2018中文版软件基础教学知识 SolidWorks自学教程软件操作教程 sw视频教程 零基础教程 视频教程】 h…...

Redis经典五大类型源码及底层实现(一)

👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术🔥如果感觉博主的文章还不错的…...

数据库闭包求法 附相关习题及解析

闭包就是由一个属性直接或间接推导出的所有属性的集合 以下是写的比较科学规范的闭包求解方法,设X和Y均为关系R的属性集的子集,F是R上的函数依赖集,若对R的任一属性集B,一旦X→B,必有B⊆Y,且对R的任一满足…...

idea利用JRebel插件,无需重启,实现Spring Boot项目热重载,节省开发时间和精力!

插件介绍 官方介绍 翻译过来的意思是: JRebel 是一款提高开发效率的工具,允许开发者立即重新加载代码更改。它跳过了在Java开发中常见的重新构建、重启和重新部署循环。JRebel 能够让开发者在相同的时间内完成更多工作,并且在编码时能够保持…...

学习体系结构 - AArch64内存管理

学习体系结构 - AArch64内存管理 Learn the architecture - AArch64 memory management Version 1.2 个人的英语很一般,对拿不准的翻译校准在后面添加了英文原文。 1、 概述 本指南介绍了AArch64中的内存转换,这是内存管理的关键。它解释了如何将虚拟地…...

Vue3 精通指南:如何在 setup 函数中巧妙利用 Vuex

在 Vue 3 中,如果你使用了组合式 API(Composition API),你可以通过 setup 函数来设置组件的响应式状态和逻辑。要在 setup 函数中访问 Vuex 的 $store,你可以使用 useStore 钩子,它是 Vuex 4 为 Vue 3 提供…...

Linux 服务器安全策略技巧:启用账户锁定策略

Linux 服务器安全策略技巧:启用账户锁定策略 在Linux服务器上,启用账户锁定策略是一种重要的安全措施。通过锁定账户,可以防止未经授权的访问和恶意活动。本文将介绍如何在Linux服务器上启用账户锁定策略。 什么是账户锁定策略? 账户锁定策略是一种安全措施,用于限制对…...

野火霸道-V2+3.2寸屏+FreeRTOS+LVGL移植

摘要 基于野火霸道-V23.2寸屏的开发板,下载器为STLINK分为两个版本,FreeRTOS和裸机版本 裸机 裸机准备 lvgl v8.2版本的源码野火的《触摸画板-3.2寸》与《基本定时器》的代码例程 移植 将基本定时器代码移植到触摸画板-3.2寸的例程中,…...

操作教程|MeterSphere UI测试+VNC:简单、快捷地查看UI测试实时执行详情

编者注:本文为CSDN博主hxe116的原创文章。 原文链接为:https://blog.csdn.net/hxe116/article/details/134714960?spm1001.2014.3001.5502 作为一款一站式的开源持续测试平台,MeterSphere涵盖了测试跟踪、接口测试、UI测试和性能测试等功能…...

工具--Git详解

在当今的数字时代,版本控制系统已成为开发人员和团队之间协作的重要工具。其中,Git是最受欢迎的版本控制系统之一。它不仅在软件开发中广泛使用,还被应用于许多其他领域。在这篇博客中,我们将深入了解Git的工作原理、基本命令以及…...

windows server 2022 启用SYN攻击保护

2023.12.28 SYN攻击是什么: SYN攻击是黑客攻击的常用手段,也是最容易被利用的一种攻击手法,属于DDoS攻击的一种。它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。 SYN攻击包括大量TCP连接的第一个包&…...

汽车保养软件app开发步骤

“增强您的动力,为您的旅程加油——每一刻都讲述着关爱的故事。构建汽车维护软件app,为您的车辆提供数字化的维修站,从而开启长寿之路。智能驾驶、互联驾驶、自信驾驶。” 疯狂地搜索旧收据并猜测上次换油时间的日子已经一去不复返了。如果您…...

【HarmonyOS】ArkTS语言介绍与组件方式运用

从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是…...

音频播放软件Foobar2000 mac特点介绍

Foobar2000 mac是一款高度可定制的音频播放器,适用于Windows平台。它支持各种音频格式,包括MP3、FLAC、AAC、WMA等,同时也支持各种音频插件和效果器,可以提供更好的音质和用户体验。 Foobar2000 mac软件特点 1. 高度可定制&#…...

Oracle动态性能视图 v$parameter 和 v$parameter2 的区别

v$parameter 的说明见这里: V$PARAMETER displays information about the initialization parameters that are currently in effect for the session. v$parameter2 的说明见这里: V$PARAMETER2 displays information about the initialization paramet…...

ssrf之dict协议和file协议

1.dict协议 dict是什么协议呢? 定义:词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使 用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。 官方介绍:http://dict.o…...

XCTF-web-easyupload

试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点&#xff1a; 共 6 个字段&#xff1a; Year&#xff08;年&#xff09;Month&#xff08;月&#xff09;Day&#xff08;日&#xff09;Hour&#xff08;小时&#xff09;Minute&#xff08;分钟&#xff09;Second&#xff08;秒&#xff09; 表示…...

Canal环境搭建并实现和ES数据同步

作者&#xff1a;田超凡 日期&#xff1a;2025年6月7日 Canal安装&#xff0c;启动端口11111、8082&#xff1a; 安装canal-deployer服务端&#xff1a; https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...

python3GUI--基于PyQt5+DeepSort+YOLOv8智能人员入侵检测系统(详细图文介绍)

文章目录 一&#xff0e;前言二&#xff0e;技术介绍1.PyQt52.DeepSort3.卡尔曼滤波4.YOLOv85.SQLite36.多线程7.入侵人员检测8.ROI区域 三&#xff0e;核心功能1.登录注册1.登录2.注册 2.主界面1.主界面简介2.数据输入3.参数配置4.告警配置5.操作控制台6.核心内容显示区域7.检…...

Unity基础-Mathf相关

Unity基础-Mathf相关 一、Mathf数学工具 概述 Mathf是Unity中封装好用于数学计算的工具结构体&#xff0c;提供了丰富的数学计算方法&#xff0c;特别适用于游戏开发场景。它是Unity开发中最常用的数学工具之一&#xff0c;能够帮助我们处理各种数学计算和插值运算。 Mathf…...