python 之 浮点数精度丢失例如:0.1 + 0.2,产生的原因、问题的推导、解决的方案

news2024/11/17 9:37:29

一、背景

  • 计算机基本上使用二进制数字,即 0 或 1表示;
    十进制: 1 / 3 = 0.3333333333… 无限循环的情况
    浮点数的总数是无限且不可数的,浮点数在计算机占用的内存是有限的,如果表示计算机内存则占满
    不可能用有限的内存空间存储无限多的浮点,后面多余的部分都会被砍掉

  • 计算机的浮点类型也是由二进制表示的 浮点标准
    同上并不是所有的十进制数都可以用二进制格式精确表示,
    有些是使用有限数量的二进制数字来近似的
    例如 浮点型0.1 转化二进制的结果 0.00011001100110011001100110011001100110011001100…

二、浮点数转二进制计算方法

  • 1. 对十进制小数乘2得到的整数部分和小数部分
    2. 整数部分即是相应的二进制数码
    3. 再用2乘小数部分,又得到整数和小数部分
    4. 不断重复,直到小数部分为0或达到精度要求为止
    5. 第一次所得到为最高位,最后一次得到为最低位
    
  • 0.25 * 2 = 0.5     整数部分 0    小数部分 5
    0.5  * 2 = 1.0     整数部分 1    小数部分 0
    
    浮点型0.25 转化二进制的结果 0.01
    
  • 0.8125 * 2 = 1.625  整数部分 1   小数部分 625
    0.625  * 2 = 1.25   整数部分 1   小数部分 25
    0.25   * 2 = 0.5    整数部分 0   小数部分 5
    0.5    * 2 = 1.0    整数部分 1   小数部分 0
    
    浮点型0.8125 转化二进制的结果 0.1101
    
  • 0.1 * 2 =   0.2        整数部分 0   小数部分 2
    0.2 * 2 =   0.4        整数部分 0   小数部分 4
    0.4 * 2 =   0.8        整数部分 0   小数部分 8
    0.8 * 2 =   1.6        整数部分 1   小数部分 6
    0.6 * 2 =   1.2        整数部分 1   小数部分 2
    
    0.2 * 2 =   0.4        整数部分 0   小数部分 4
    0.4 * 2 =   0.8        整数部分 0   小数部分 8
    0.8 * 2 =   1.6        整数部分 1   小数部分 6
    0.6 * 2 =   1.2        整数部分 1   小数部分 2
    ...       ....         .......
    
    浮点型0.1 转化二进制的结果 0.0001100110011001100110011001100110...
    
  • 结论
    浮点数是以二进制形式存储的,将浮点数转化为二进制过程中,也会出现无限循环的情况,造成结果的不准确

三、 浮点数精度丢失解决 例如:0.1 + 0.2 问题

浮点数精度丢失通常在涉及不能精确表示为有限小数的数字时发生,
例如 0.1 或 0.2 这样的数字,因为它们在二进制表示中是无限循环小数。
由于计算机的二进制表示是有限的,所以在转换为二进制表示时会有一定的近似,从而导致小数的精度问题。

一、背景

  • 计算机基本上使用二进制数字,即 0 或 1表示;
    十进制: 1 / 3 = 0.3333333333… 无限循环的情况
    浮点数的总数是无限且不可数的,浮点数在计算机占用的内存是有限的,如果表示计算机内存则占满
    不可能用有限的内存空间存储无限多的浮点,后面多余的部分都会被砍掉

  • 计算机的浮点类型也是由二进制表示的 浮点标准
    同上并不是所有的十进制数都可以用二进制格式精确表示,
    有些是使用有限数量的二进制数字来近似的
    例如 浮点型0.1 转化二进制的结果 0.00011001100110011001100110011001100110011001100…

二、浮点数转二进制计算方法

  • 1. 对十进制小数乘2得到的整数部分和小数部分
    2. 整数部分即是相应的二进制数码
    3. 再用2乘小数部分,又得到整数和小数部分
    4. 不断重复,直到小数部分为0或达到精度要求为止
    5. 第一次所得到为最高位,最后一次得到为最低位
    
  • 0.25 * 2 = 0.5     整数部分 0    小数部分 5
    0.5  * 2 = 1.0     整数部分 1    小数部分 0
    
    浮点型0.25 转化二进制的结果 0.01
    
  • 0.8125 * 2 = 1.625  整数部分 1   小数部分 625
    0.625  * 2 = 1.25   整数部分 1   小数部分 25
    0.25   * 2 = 0.5    整数部分 0   小数部分 5
    0.5    * 2 = 1.0    整数部分 1   小数部分 0
    
    浮点型0.8125 转化二进制的结果 0.1101
    
  • 0.1 * 2 =   0.2        整数部分 0   小数部分 2
    0.2 * 2 =   0.4        整数部分 0   小数部分 4
    0.4 * 2 =   0.8        整数部分 0   小数部分 8
    0.8 * 2 =   1.6        整数部分 1   小数部分 6
    0.6 * 2 =   1.2        整数部分 1   小数部分 2
    
    0.2 * 2 =   0.4        整数部分 0   小数部分 4
    0.4 * 2 =   0.8        整数部分 0   小数部分 8
    0.8 * 2 =   1.6        整数部分 1   小数部分 6
    0.6 * 2 =   1.2        整数部分 1   小数部分 2
    ...       ....         .......
    
    浮点型0.1 转化二进制的结果 0.0001100110011001100110011001100110...
    
  • 结论
    浮点数是以二进制形式存储的,将浮点数转化为二进制过程中,也会出现无限循环的情况,造成结果的不准确

三、 浮点数精度丢失解决 例如:0.1 + 0.2 问题

浮点数精度丢失通常在涉及不能精确表示为有限小数的数字时发生,
例如 0.1 或 0.2 这样的数字,因为它们在二进制表示中是无限循环小数。
由于计算机的二进制表示是有限的,所以在转换为二进制表示时会有一定的近似,从而导致小数的精度问题。

0.1  0.00011001100110011001100110011001100110011001101...
0.2  0011001100110011001100110011001100110011001100110...

python是以双精度(64bit)来保存浮点数的,后面多余的会被砍掉,所以在电脑上实际保存的已经小于0.1的值了,后面拿来參与运算就产生了误差

在这里插入图片描述

  • 对稳定性、安全性要求非常高的程序,尽量避开浮点数
  • 使用 Decimal 类型:提供了更高的精度,能避免浮点数运算的一些常见问题
    from decimal import Decimal
    a = Decimal('0.1') + Decimal('0.2')
    print(float(result))  # 将结果转换为浮点数输出,得到正确的结果:0.3
    

四、0.1 + 0.3 呢

0.1(10)0.0001100110011001100110011001100110011001100110011001101...(2)
0.3(10)0.0100110011001100110011001100110011001100110011001101...(2)
0.0001100110011001100110011001100110011001100110011001101...(2) 
+
0.0100110011001100110011001100110011001100110011001101...(2)
=
0.0110011001100110011001100110011001100110011001101101...(2)

将上述二进制结果转换回十进制,它大约等于 0.4(10)。
注意,这个结果仍然是一个近似值,因为我们只取了有限位数的二进制表示进行计算。

0.1 + 0.3二进制    0.0110011001100110011001100110011001100110011001101101...
0.4  二进制        0.0110011001100110011001100110011001100110011001100110...

在十进制中,0.1 + 0.3 确实等于 0.4。
在计算机内部,由于浮点数的二进制表示和有限精度,0.1 + 0.3 的二进制近似值并不等于 0.4 的二进制近似值。
因此,在某些情况下,由于浮点数精度问题,可能会导致 0.1 + 0.3 不等于 0.4。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka 入门到起飞系列 - 到底什么是再平衡?谁来执行再平衡呢?什么是组协调器呢?

再平衡(Rebalance) 本质上是一种协议,规定了一个消费组中所有消费者如何达成一致来分配订阅主题的每个分区 其实就是建立分区和消费者映射关系的这么一个过程,最终主题下的一个分区只会分配给一个消费者 比如有10个分区&#xff…

个人博客系统 -- 登录页面添加图片验证码

目录 1. 功能展示 2. 前段代码 3. 后端代码 1. 功能展示 在登录页面添加验证码登录 1. 检测到没有输入验证码或者输入的验证码错误时,进行弹窗提示.并且刷新当前验证码图片 2. 点击验证码进行刷新 2. 前段代码 1. 添加验证码标签,在密码的下面,在login.html进行修改 主要…

多模态预训练 + 自监督学习 + 下游任务介绍

预训练 1)特征提取要解决的问题是怎么分别量化文字和图像,进而送到模型学习? 特征抽取: 文本:倾向于bert等大模型 图像:神经网络,VIT等 2)特征融合要解决的问题是怎么让文字和图像的表征交…

基于Java+SpringBoot+vue前后端分离社区医院信息平台设计实现

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

Hadoop_HDFS_常见的文件组织格式与压缩格式

参考资料 1. HDFS中的常用压缩算法及区别_大数据_王知无_InfoQ写作社区 2. 本文主要介绍下HDFS上的常见文件格式和压缩格式 总结 : HDFS 中常见的文件存储格式 textfile :行式存储格式sequencefile :行式存储格式orc :列式存储格式, 支…

Deployment 升级应用2

上次我们说到自己手动的做使用 RS 的方式来升级 pod ,感觉还是蛮复杂的,并且容易弄错,实际生产过程中,肯定不会这样来弄,很危险 那么今天我们来分享 Deployment 的方式来显示的升级应用吧 Deployment 的方式升级应用…

3dmax崩溃后如何恢复文件?

当意外或突然关闭 3ds Max 场景时,有时会出现恢复 3ds Max 场景的问题。在处理任何项目的过程中,有时需要恢复 3ds Max 场景,为此在专用文件夹中创建备份副本。如果您使用的是 Windows 操作系统并且未更改项目位置或不知道项目位置&#xff0…

如何通过nginx代理实现外网访问内网mysql或oracle数据库

项目开发部署中经常会遇到MySQL或Oracle数据库安装在内网,而我们的应用服务只能部署在外网,如果实现外网服务访问连接内网的数据库呢?本次介绍如何通过Nginx配置实现外网访问内网数据库。 1、前置机服务器 首先要保证有一台前置机服务器既可…

为Android构建现代应用——主体结构

创建Screents和ViewModels 在前面的章节中,我们已经分析了OrderNow项目的理论概念和我们将赋予的组织。 在本章中,我们将开始实现初始结构和模板,这将联接每一个应用程序的部分。 首先将添加以下带有各自视图模型的主屏幕: •…

到底什么是前后端分离

目录 Web 应用的开发主要有两种模式: 前后端不分离 前后端分离 总结 Web 应用的开发主要有两种模式: 前后端不分离 前后端分离 理解它们的区别有助于我们进行对应产品的测试工作。 前后端不分离 在早期,Web 应用开发主要采用前后端不…

“云上新气象”,VDI+IDV混合部署,麒麟信安云正式上线某市气象局!

阴晴冷暖,风云变幻,气象与人们的生活密切相关,气象局信息系统的智慧高效运营对于提升灾害防御能力、城市气象观测等方面具有重要作用,随着气象业务范围的不断扩展,气象局的信息化建设与数字化转型也亟需提上日程。 走…

【Solr】Solr搜索引擎使用

文章目录 一、什么是Solr?二 、数据库本身就支持搜索啊,干嘛还要搞个什么solr?三、如果我们想要使用solr那么首先我们得安装它 一、什么是Solr? 其实我们大多数人都使用过Solr,也许你不会相信我说的这句话,但是事实却是如此啊 ! 每当你想买自己喜欢的东东时,你可能会打开某…

Python入门准备

安装并配置Python 1、想要更新终端里Python的版本: 在python.org官网上下载最新版,下载安装以后,在终端输入python3进行询问。 2、完成Python环境的安装(Linux:操作系统,基于Cent0S7) 在Linux系统上安装Python需要…

中小学分班查询系统如何制作?这个方法3分钟轻松搞定

暑假一过完,新学年即将开始,学校面临着一个重要的任务:学生分班。无论是新生入学还是低年级升高年级,都需要进行分班工作。这对负责分班的老师们来说,增加了相当大的工作量和挑战。 在开学前,如何快速搞定…

Pure Admin 图标篇

1. 官方图标讲解地址 B站搜索:vue-pre-admin之图标篇,作者“乐于分享的程序员小铭” 2. 实操 1. iconify官网 Icon Sets • Iconify 2. 在build->optimize.ts 中,配置所用的Iconify icon包 如: "iconify-icons/ep&quo…

LNK 2001 问题的一种解决办法

问题: 可能有这样的报错,error LNK 2001: 无法解析的外部符号" protected: virtual void __thiscall testing::Test::SetUp(void)"。 解决办法: 换了各编译器就好了,从第二个换到了第一个。 猜测:这里是因…

开江县“五社联动 关爱一老一小“主题活动之银龄爱齿健康关爱计划

为进一步宣传和推动“五社联动”关爱“一老一小”的社工服务理念,近日,开江县网格员社会工作服务中心携手彭州市葡萄树社会工作服务中心链接爱心单位(夜郎古酒)捐赠的1440支牙膏(合和泰品牌牙膏)&#xff0…

Electron从构建到打包程exe应用

Electron从构建到打包程exe应用 Electron文档搭建网页装载到 BrowserWindow中定义全局对象进程之间通信打包应用程序对代码进行签名 Electron文档 搭建 创建一个文件夹,在根目录执行以下几个命令 1.npm init 2.npm install electron --save-dev 3.根目录新增main…

route_group时调整routing rule via array大小

使用route_group secondary pg pin时需要multi via/double via,可以使用如下办法。 用create_routing_rule -vias {{via_def_name array_size NR/R} {xx xx xx}} R和NR就是能不能旋转 set_routing_rule net_name -rule rule_name -max_routing_layers MEx -max_la…

RHCSA(一)

1、在VMware上创建虚拟机以及安装Linux操作系统,使用ssh进行远程连接 1.创建虚拟机 2.安装Linux系统 3.使用Xshell进行远程ssh连接终端 进入了Linux系统,打开终端输入ifconfig回车得到了虚拟网卡的IP地址为192.168. 163.128 打开Xshell远程连接软件…