老生常谈之 JavaScript 中 0.1 + 0.2 != 0.3 的原因

2023-11-23 14:12

本文主要是介绍老生常谈之 JavaScript 中 0.1 + 0.2 != 0.3 的原因,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先来一个模棱两可的说法:因为精度丢失、存储溢出的问题

先复习一下二进制的转换方法:

  1. 整数:除以基数,取余,自底向上
  2. 小数:乘以基数,取整,自顶向下
    二进制转换

接着,复习一下双精度浮点数(double)

  1. Number 类型使用IEEE754 标准 64位 存储
  • 符号位:1位,0 表示正数,1 表示负数
  • 指数位:11位,固定值(1023)+ 指数实际值
    • (2 ^ (e-1)) - 1 => (2 ^ (11 - 1)) - 1 = 1023
    • 这一步看不懂,可先跳过,待会解释
  • 小数位:52位
  1. 双精度浮点数即为每个数值分配 64位存储空间,以科学计数法的方式存储

中间插播一个小内容:怎么理解指数位

1、IEEE 754 标准中的双精度浮点数采用了带有偏移量的指数表示
2、具体来说,双精度浮点数的指数部分是一个11位的二进制数,其中最小值是全0(00000000000),最大值是全1(11111111111)。这11位的二进制数会被解释为一个无符号整数,然后从中减去一个偏移值来得到最终的指数。
3、IEEE 754 双精度浮点数的指数偏移值是 2 ( k − 1 ) − 1 2^{(k-1)} - 1 2(k1)1,其中 k 是指数部分的位数。对于双精度浮点数,k 是11,所以偏移值是 2 ( 11 − 1 ) − 1 = 1023 2^{(11-1)} - 1 = 1023 2(111)1=1023
4、例如,如果指数部分的二进制表示是 01111111111,那么对应的无符号整数是 2 10 − 1 = 1023 2^{10} - 1 = 1023 2101=1023。然后,减去偏移值 1023,最终得到实际的指数值为0。
5、这个偏移量的使用允许浮点数表示非常大和非常小的数,因为指数的范围可以从负数到正数。同时,由于使用偏移值,指数部分的二进制表示中并不包含真实的指数值,而是需要通过减去偏移值来得到真实的指数。

了解上面两个知识点之后,开始进入正文
第一步:0.1 转换二进制为:0.00011001…1001(循环)
第二步:二进制转换为科学计数法 = 1.1001 * 2^ (-4)
第三步:计算指数位 1023 + (-4) = 1019 = 01111111011
第四步:计算小数位,为1001无限循环
因此,0.1 = 符号位0 + 指数位01111111011 + 小数位1001…

由于小数位只有52为,因此第53位为1,截取保存的时候进了1,所以发生了精度丢失。 即后四位小数为 1001 + 1 = 1010

针对于0.2也进行同样分析,相加的时候同样也出现了截取保存的情况,即出现第二次精度丢失,所以最终转换为10进制的时候为 0.30000000000000004

综上所述:
1、由于js采用二进制处理数据,用IEEE 754双精度浮点数标准来存储 Number 类型
2、精度丢失非JS问题,而是IEEE 754标准存储位有限
3、过程中出现了两次精度丢失问题,一次在存储,一次在相加

解决方案:
1、两个数分别乘以100,得到结果再除以100

这篇关于老生常谈之 JavaScript 中 0.1 + 0.2 != 0.3 的原因的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

Java中Integer128陷阱

《Java中Integer128陷阱》本文主要介绍了Java中Integer与int的区别及装箱拆箱机制,重点指出-128至127范围内的Integer值会复用缓存对象,导致==比较结果为true,下... 目录一、Integer和int的联系1.1 Integer和int的区别1.2 Integer和in

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

JSONArray在Java中的应用操作实例

《JSONArray在Java中的应用操作实例》JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端... 目录1. jsONArray定义与功能1.1 JSONArray概念阐释1.1.1 什么是JSONA

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与