2019独角兽企业重金招聘Python工程师标准>>>

这是在其他地方看到的一个提问,提问原文链接:https://www.oschina.net/question/2346828_2266386?sort=default#comments

如下代码示例,问0.7在计算机中应该是无法精确存储的,那为什么可以输出0.7?

public void test() {double a = 0.7;System.out.println(a);}

看了几个答案,感觉都没有明确回答问题,或是没有说清楚,我试着解答一下。看提问的代码是java,所以我也用java回答,先看如下的代码:

public static void main(String[] args) {float a = 0.7f;float b = 0.69999996f;float c = 0.70000001f;System.out.println(a);  //0.7System.out.println(b);  //0.7System.out.println(c);  //0.7System.out.println(Integer.toUnsignedString(Float.floatToIntBits(a), 16));//3f333333System.out.println(Integer.toUnsignedString(Float.floatToIntBits(b), 16));//3f333333System.out.println(Integer.toUnsignedString(Float.floatToIntBits(c), 16));//3f333333System.out.println(a==b); //trueSystem.out.println(a==c); //truefloat d = 0.70000002f;System.out.println(d);    //0.70000005System.out.println(Integer.toUnsignedString(Float.floatToIntBits(d), 16));//3f333334}

第一个问题: 提问者说0.7在计算机中应该是无法存储的。

不是应该,而是肯定无法精确存储,因为java中也遵循IEEE 754浮点数的二进制表示规范,所以肯定无法精确存储。上面代码中a=0.7f, b=0.69999998f, c=0.70000001的值在java中都是3f333333,在java看来它们是一样的,都是0.7。按IEEE 754标准手工计算一下,3f333333换算回来大约是0.699999988,当然这个值的最后一位在java中是省略的。

第二个问题:为什么可以输出0.7?

明白了0.7在java内存中的存储形式,就知道了,在java中0.7的表示形式就是3f333333,这个就是0.7。不管你开始给变量赋值是用a, b 还是c, 他们在内存中的表示是一样的,所以输出都是0.7。所以根本就不存在为什么可以输出0.7的问题,因为是0.7肯定要输出0.7。

其实提问者想搞明白的问题是:为什么不是输出0.699999988这样的形式。

这个其他回答其实也解释了,就是精度问题,但没有说透,我再来解释一下。

以IEEE 754单精度为例,在位数固定32的情况下,尾数部分的位数23位也是固定的,所以需要用超过23位才能表示的数,超过部分就被省略了,示例的0.7就是这样的数,有省略。这个角度是一般人都理解的。

但还有另一个角度,就是数的个数问题。大部分人对IEEE 754单精度能表示的数字范围(±3.4×10^38)没有深入的理解。固定32位的长度能够表示的数字个数是有限的,表示范围确定以后,在一个小的区间中,能够表示的数字的个数就很有限了。两个值比较接近的浮点数相减,则会产生一个极小的浮点数,这种情况下如果省略过多,则大量计算就无法精确表示了,基本都是0了。这也是为什么IEEE754规定了两种形式的浮点数:规约形式与非规约形式。其目的就是:让有限的能表示的数的个数,在整个表数范围内,不再均匀分配。

有了这两个角度,那就可以想明白了。若把IEEE 754能表示的所有数都画在一条数轴上,那么会看到能表示的两个数字之间是有间隔的,且间隔在0的附近比其他地方要小,也就是在0附近数比较密集。在能表示的两个数字之间的数,在计算机看来都是同一个数。如:a=0.7f, b=0.69999998f, c=0.70000001 是同一个数,这里要注意不是说的b最后一位进位了,c的最后一位省略了。而是这几个数在按IEEE 754标准存到计算机中时,尾数23位满了,但后边还有,把后边的省略了。省略之后,剩下的全部一样,所以计算机认为他们是一个数。

如果看到这里还表示不明白,那就只能用代码中的d = 0.70000002f 这个例子说明一切了。因为这个变量d输出值是 0.70000005,明显这输入计算机的值和输出的值根本不一样。

最后,千言万语化成一句解释:输入0.7,输出也是0.7,只是碰巧而已,换个数就没这么幸运了。

转载于:https://my.oschina.net/jasonli0102/blog/3013198

浮点数0.7在Java中是无法精确存储的,却为何能精确输出0.7相关推荐

  1. Java基础题37:(单选题)java中char类型的取值范围是() A.0 ... 32767 B.0 ... 65535

    37.(单选题)java中char类型的取值范围是() A.0 - 32767 B.0 - 65535 C.–256 - 255 D.–32768 - 32767 [正确答案]B [答案解析]在jav ...

  2. java中char类型可以存储两个中文字符吗

    java中char类型只能存储一个中文字符 https://www.cnblogs.com/lchzls/p/7071862.html https://blog.csdn.net/qq_4264294 ...

  3. 利用JAVA中关于继承的相关知识求得圆柱体体积并输出

    利用JAVA中关于继承的相关知识求得圆柱体体积并输出 Write a program: 1)Define a Circle class and a Cylinder class, which is d ...

  4. 深入理解计算机系统(2.8)---浮点数的舍入,Java中的舍入例子以及浮点数运算(重要)

    https://www.cnblogs.com/zuoxiaolong/p/computer12.html 前言 上一章我们简单介绍了IEEE浮点标准,本次我们主要讲解一下浮点运算舍入的问题,以及简单 ...

  5. java cursor_使用3.0驱动程序的Java中的Tailable Cursor示例?

    有人可以在 Java中提供完整的tailable游标示例吗?我使用3.0驱动程序,所有示例似乎是2.x.我的classpath中只有mongo-java-driver-3.0.0.jar.我希望得到所 ...

  6. Java中数据是如何存储

    2019独角兽企业重金招聘Python工程师标准>>> 一:JAVA中数据的存储方式 ①:寄存器:这是最快的存储区,因为它位于不同于其他存储区的地方---处理器内部.但是寄存器的数量 ...

  7. Java中的线程本地存储

    开发人员中鲜为人知的功能之一是线程本地存储. 这个想法很简单,并且在需要数据的情况下很有用. 如果我们有两个线程,则它们引用相同的全局变量,但我们希望它们具有彼此独立初始化的单独值. 大多数主要的编程 ...

  8. 将Java中的内容直接存储为二进制文件

    目前有这个需求,需要将java跑好的结果持久化,但是如果一个个输出为文本文件又不太好办,因为里面东西太多太杂,所以最好的办法是直接输出为二进制文件,把数据连同存储数据的类一起存进去,就行python中 ...

  9. Java中当被除数比除数小时为什么计算结果都为0?

    前段时间写项目时遇到了这个问题,现在记录一下,帮助已经入坑的各位早点儿出坑. 首先,要区分清楚什么是被除数.什么是除数,话不多说,直接上图: 比如100/50,其实就是100÷50,那么100就是被除 ...

最新文章

  1. ASCII码对应表,ASCII码值的大小顺序
  2. 将PS/2接口鼠标改造成USB接口鼠标
  3. 经常误提交.DS_Store文件怎么办?Git全局排除配置了解一下!
  4. Redis配置主从数据,实现主从库之间数据同步
  5. DButils的更新与查询,利用C3P0链接数据库
  6. C#在winform中调用系统控制台输出
  7. 第7章 实战演练:爬取百度百科1000个页
  8. 闲来无事,就把lnmp的php升级到php-5.2.17最新稳定版本
  9. 2018.4.23 数据结构
  10. 前端会有什么新的变化
  11. java wsdl接口地址_java如何实现webservice中wsdlLocation访问地址的可配置化
  12. iweboffice2015库文件WebOffice.js中新增删除两个书签之间的内容实现
  13. 【WPF】 免费图表控件的比较 (OxyPlot,LiveChart,ScottPlot,MsChart)
  14. 两个表格数据合并怎么完成?
  15. linux6.5 xmanager配置,CentOS6.5安装Xmanager远程桌面
  16. 2021年焊工(初级)考试题及焊工(初级)考试试卷
  17. Linux源码编译安装步骤及命令
  18. PyQt5 的textedit下的setPlainText()和setText区别
  19. HTTP中get和post方法的区别
  20. xss获取键盘记录实验演示

热门文章

  1. Android11 九宫格解锁流程
  2. ASP.NET- 播放视频代码
  3. maya原创mel插件缺少新版linkDll_2024版本库更新
  4. 听说拍人家违章月入十万?那我写了个自动检测车辆是否违章不发财了
  5. 自动驾驶仿真科普文之二:传感器的仿真究竟难在哪?
  6. 迷人的海湾—止锚湾(2)
  7. 3.Unity3D商业游戏源码研究-变身吧主公-SceneBase
  8. 前端战五渣学前端——跨域
  9. 机械自动化Pk计算机专业,机械与自动化专业主要学什么 就业方向有哪些
  10. 计算机图形学上机报告绘制圆,计算机图形学上机实验报告