0.1+0.2 != 0.3 (Java为例)

news/2024/9/19 15:46:00/文章来源:https://www.cnblogs.com/larissa-0464/p/18405612

1. 小数的二进制表示

以10.625为例。整数部分进行除2取余的操作,10的二进制为1010。小数部分进行乘2取整操作,直到小数部分为0或达到需要的精度:

  • 0.625*2=1.25 取整数1,小数部分0.25继续计算
  • 0.25*2=0.5 取整数0,小数部分0.5继续计算
  • 0.5*2=1.0 取整数1,小数部分为0,停止计算

因此0.625对应的二进制为101。10.625对应的二进制为1010.101。

可以发现,一些小数对应的二进制数是无法精确表示出来的。例如0.1的二进制数为:

  • 0.1*2=0.2 取整数0,小数部分0.2继续计算
  • 0.2*2=0.4 取整数0,小数部分0.4继续计算
  • 0.4*2=0.8 取整数0,小数部分0.8继续计算
  • 0.8*2=1.6 取整数1,小数部分0.6继续计算
  • 0.6*2=1.2 取整数1,小数部分0.2继续计算
  • 产生循环

因此,0.1对应的二进制数为:0.00011001100110011...

 

2. IEEE 754标准

二进制浮点数算术标准,详见百度。这里仅以double为例,不涉及float。

IEEE 754定义的double(64-bit)由三部分组成:

  • 符号位(1-bit): 0表示正数,1表示负数
  • 指数位(11-bit):表示浮点数的指数,采用偏移量的存储方式,偏移值为1023
  • 尾数位(52-bit):表示有效数字,默认是1.xxxx的形式

例如,10.625对应的二进制为1010.101,小数点左移3位得到其标准化形式为:1.010101*2^3。指数为3,加上偏移量1023,可得指数位为1026。相应的二进制为10000000010。尾数位则为010101。故10.625符合IEEE 754标准的二进制为:

0 10000000010 01010100000000...补齐52bit。

在Java中对比一下:

double d1=10.625;
long valBits=Double.doubleToLongBits(d1);
System.out.println(Long.toBinaryString(valBits));// 输出为:100000000100101010000000000000000000000000000000000000000000000,前面加个0,补齐64-bit

 

类似地,0.1的二进制标准化形式为:1.1001100110011...*2^(-4)。指数为-4,加上偏移量1023,则指数位为:1019,二进制为01111111011。故0.1符合IEEE 754的二进制为:

0 01111111011 1001100110011001100110011001100110011001100110011010

 

符合IEEE 754标准的二进制数再转换为十进制,可使用如下公式:

其中,e为指数位对应的十进制数,f为尾数位对应的十进制数(小数)。

先不考虑符号sign和f部分的系数(即二进制中的0和1),可知:

利用上述公式计算得到符合IEEE 754标准的0.1的二进制再转换为十进制的值为:

0.1000000000000000055511151231257827021181583404541015625

 

3. 0.1+0.2=?

0.1符合IEEE 754标准的二进制表示为(指数位为1019,指数为-4):

0 01111111011 1001100110011001100110011001100110011001100110011010

0.2符合IEEE 754标准的二进制表示为(指数位为1020,指数为-3):

0 01111111100 1001100110011001100110011001100110011001100110011010

先将二者的指数对齐(向大指数对齐)。即0.1的尾数右移一位(相当于小数点左移一位)。移位后尾数变为:

1100110011001100110011001100110011001100110011001101

然后与0.2的尾数相加可得:

0.1100110011001100110011001100110011001100110011001101 +

1.1001100110011001100110011001100110011001100110011010=

10.0110011001100110011001100110011001100110011001100111

将尾数标准化,指数+1,尾数右移1位。

0011001100110011001100110011001100110011001100110011(1)

可见末尾的1会被移除掉,这时会向上舍入(如果末尾是0,则直接舍掉了),尾数变为了:

0011001100110011001100110011001100110011001100110100

最终0.1+0.2的结果的二进制为:

0 01111111101 0011001100110011001100110011001100110011001100110100 

转换为十进制为:0.300000000000000044408920985006261616945266723632812500

public static void main(String[] args){double d1=0.1;double d2=0.2;double d3=d1+d2;System.out.println(d3);
}
// 输出为:0.30000000000000004

 

但是0.3符合IEEE 754标准的二进制是:

0 01111111101 0011001100110011001100110011001100110011001100110011 

转换为十进制为:0.299999999999999988897769753748434595763683319091796875

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

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

相关文章

信创领域认证,来自工信部人才交流中心的PostgreSQL培训班

在国家大力发展信创软件和数据库行业的背景下,PostgreSQL 具有多方面的优势和机遇,具体体现在以下几个方面: 1. 技术优势契合信创需求: PostgreSQL 数据库是一个功能强大、性能稳定、可扩展性强的开源对象关系数据库系统,支持多种数据类型(如数组、JSON、XML 等),方便存储…

Salesforce职业规划:原厂,甲方,乙方,从业者应该如何选择?

Salesforce生态系统蓬勃发展,对不同角色的需求量不断增加。需求方包括使用Salesforce的最终用户(甲方)、实施Salesforce的咨询公司、为Salesforce创建应用程序的AppExchange公司(或ISV),当然还有Salesforce原厂。 Salesforce最终用户(甲方) 2020年,Salesforce的客户数…

3SRB5016-ASEMI三相整流桥3SRB5016

3SRB5016-ASEMI三相整流桥3SRB5016编辑:ll 3SRB5016-ASEMI三相整流桥3SRB5016 型号:3SRB5016 品牌:ASEMI 封装:3SRB-5 批号:2024+ 现货:50000+ 最大重复峰值反向电压:1600V 最大正向平均整流电流(Vdss):50A 功率(Pd):大功率 芯片个数:5 引脚数量:5 安装方式:直插 类…

34-样式迁移

类似于加了一层滤镜基于CNN的样式迁移:如下对于合成图片X,我们希望它的内容和输入的内容图片,放入同一个CNN,在某一个卷积层上,输出的与内容有关的特征能够匹配 同时,,对于样式图片,我们希望合成图片X,和样式图片放入同一个CNN,在某一个卷积层上,输出的与样式有关的…

STM32-ADC外设

1.通道 .规则通道 .注入通道 2.规则序列寄存器 配置通道的采样顺序 3.ADC周期4.ADC转换方式 *单次转换:adc每次只采集某个通道的一个点,如果需要再次采集,就需要重新使能。 *连续转换:adc采集某个通道一个点,转换完成后,再采集第二点。依次类推 4.扫描模式 *单次扫描模式…

SignalR跨域问题解决

本文来自博客园,作者:WantRemake,转载请注明原文链接:https://www.cnblogs.com/SmallChen/p/18406437

字符串类

常用类String基础知识String类的特性String类是一个final类,不能被继承 String类底层是一个final修饰的字符数组,表示不可变的字符序列(final char value[ ]) String的不可变性:当String值改变时,会在常量池中创建新的字符串字符串-创建字面量方式创建 String s1="a…

AI答案之书解来为你解决难题

本文由 ChatMoney团队出品介绍说明 “答案之书智能体”是您贴心的智慧伙伴,随时准备为您解答生活中的种种困惑。无论您在工作中遭遇瓶颈,还是在情感世界里迷失方向,亦或是对个人成长感到迷茫,它都能倾听您的心声,并给予准确且富有启发的回应。 它并非简单地给出答案,而是…

解锁生活密码,AI答案之书解决复杂难题

本文由 ChatMoney团队出品介绍说明 “答案之书智能体”是您贴心的智慧伙伴,随时准备为您解答生活中的种种困惑。无论您在工作中遭遇瓶颈,还是在情感世界里迷失方向,亦或是对个人成长感到迷茫,它都能倾听您的心声,并给予准确且富有启发的回应。 它并非简单地给出答案,而是…

STM32F7外设FMC控制LCD显示屏

STM32F7外设FMC控制LCD显示屏, 显示屏的点阵LCD控制器(Dot Matrix LCD Controller/Driver)是ST7066U。 配置 在CubeMX中选择图 1 根据实际情况选择,Bank几,LCD片选引脚。图 2 FMC原理 对于FMC如何控制LCD,我的理解: FMC能自动发送数据读写RAM,通过FMC读写LCD的显存就可以…

推荐一款好用的golang修复无效json的库:JSONRepair

简单来说,就是可以将错误格式(非标准)的json修正,如下图所示: 我的json明显不是标准的json格式,是不能被解析的: 但是JSONRepair库也能修复。github地址:https://github.com/kaptinlin/jsonrepair 使用也非常简单: 1、安装:go get github.com/kaptinlin/jsonrepair2、…