首页 > 编程语言 >0.1+0.2 != 0.3 (Java为例)

0.1+0.2 != 0.3 (Java为例)

时间:2024-09-10 15:51:26浏览次数:12  
标签:754 0.1 0.3 0.2 二进制 IEEE 小数

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

标签:754,0.1,0.3,0.2,二进制,IEEE,小数
From: https://www.cnblogs.com/larissa-0464/p/18405612

相关文章

  • PFTL301E-0.1KN 张力压头
    PFTL301E0.1KN3BSE019050R100是ABB生产的压磁压头,特别适用于线圈加工行业的卧式Mini系列枕式压头。该产品的设计使其只能测量线圈张力的水平分量,而不是像传统压头那样测量垂直分量和张力辊的重量。这种设计允许压头在测量范围内发挥最佳性能,即使在辊重较大而张力较小的情......
  • 经销商订货管理系统V1.0.1
    订货管理系统适用于经销商订货、连锁加盟门店订货、批发贸易订货等。为连锁型品牌、商贸批发类或工厂企业客户提供支持业务模式的分成数字化营销方案。提供前后端无加密源码,独立部署,不受限制。V1.0.1增加差价分成1、增加差价分成2、增加再次订购3、其他优化......
  • 记录一次【截止目前最新版本MySql安装教程】MySql-9.0.1-winx64
    本次记录是目前最新版本9.0.1的安装记录,跟之前版本还是有区别的MySQL社区版下载地址:https://dev.mysql.com/downloads/mysql/安装整体步骤如下:下载MySQL版本;配置环境变量也可以不配置配置安装配置文件my.ini执行安装命令mysqld--install创建随机密码mysqld--initialize--con......
  • AJAX家政系统V1.0.1
    原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统,用户端、服务端(高级授权)、门店端(高级授权)各端相互依赖又相互独立,支持选择项目、选择服务人员、选择门店多种下单方式,支持上门服务和到店核销两种服务方式,支持自营和多商家联营(高级授权)两种运营模式,同时支持多城......
  • 沃德校友会管理系统V1.0.1
    校友会综合服务平台,即校友信息管理平台、活动管理平台、校友服务大厅、校友企业服务平台等,实现集中学校、学院、校友会于一体的基础服务平台的搭建,建设一个满足校友信息化长期发展的、可扩展的综合校友服务平台,提供全部无加密源代码,支持私有化部署。目前Uniapp仅支持编译微信小程序......
  • 0.1 + 0.2 不等于 0.3?
    问题在计算机编程中有时会遇到一些需要做分支判断的情况,例如:if(0.1+0.2==0.3){cout<<"yes"<<endl;}else{cout<<"no"<<endl;}但是最后发现走的分支一直都是else的分支,为什么会出现上述的原因呢?这是因为在计算机中使用的是二进制的浮点数,通常使用IEEE75......
  • AJAX家政系统V1.0.1
    一款同城预约、上门服务、到店核销家政系统,用户端、服务端(高级授权)、门店端(高级授权)各端相互依赖又相互独立,支持选择项目、选择服务人员、选择门店多种下单方式,支持上门服务和到店核销两种服务方式,支持自营和多商家联营(高级授权)两种运营模式,同时支持多城市并且设置每个城......
  • centos7.9安装mysql8.0.39
    1.添加MySQLYum仓库首先,需要下载并安装MySQLYum仓库RPM包:sudorpm-Uvhhttps://repo.mysql.com/mysql80-community-release-el7-3.noarch.rpm2.更新Yum缓存安装完Yum仓库后,更新Yum缓存:sudoyumcleanallsudoyummakecache3.安装MySQL 现在可以......
  • 【2024潇湘夜雨】WIN11_PWK_21H2.22000.3147软件选装纯净特别版9.08
    【系统简介】=============================================================1.本次更新母盘来自WIN11_PWK_21H2.22000.3147(专业工作站版).2.全程离线精简、无人值守调用优化处理制作。部分优化适配系统可能要重启几次,即使显示适配失败也不要在意,可能部分优化不适用。3.OS版本号为2......
  • Gitlab-ce upgrade 16.0.1 to 17.3.1【Gitlab-ce 16.0.1 升级 17.3.1】
    文章目录背景gitlab-ce16.0.1升级17.3.1失败gitlab-ce16.0.1升级16.11.8失败gitlab-ce16.0.1升级16.7.9失败gitlab-ce16.0.1升级16.3.8成功gitlab-ce16.3.8升级16.11.8失败gitlab-ce16.3.8升级16.7.9成功gitlab-ce16.7.9升级16.11.8成功gitlab-ce16.......