double精度丢失问题

从二进制角度考虑问题就会很简单了:把「0.1」转成二进制然后还原成十进制,就能看出问题。

  • 这是二进制与十进制之间的碰撞
  • 这是机器与人们之间的差异
  • 这是思想与结果的碰撞
  • 理解之后一切都会变得合理……毕竟称之为浮点数

一、把 0.1 转成二进制表示

我们知道 DEC(1) 就是 BIN(1),但是 DEC(0.1) 怎么转换成二进制?

是的!用除法:

0.1 = 1 ÷ 10

很简单,二进制就是要算

1 ÷ 1010

我们回到小学的课堂,来列竖式吧:(算了还是用计算器来的更快些……)

       0.000110011.../------------------
1010 / 1 0000/    1010------11001010----100001010-----11001010----10

这时候你一定会发现,除不尽,除出了一个无限循环小数:二进制的 0.0001100110011…

二、机器语言的舍入

我们得把 0.0001100110011… 放进一个 double「双精度浮点数」里面,机器容量有限,不可能存储无限循环小数,只能存储部分

双精度浮点数能表示多少精度呢?查看文档会发现:

  • 半精度(16bit) : 11 位有效数字
  • 单精度(32bit) : 24 位有效数字
  • 双精度(64bit) : 53 位有效数字
  • 四精度(128bit):113 位有效数字

好吧,双精度是 53 位有效数字

0.00011001100110011001100110011001100110011001100110011001  10011...

方便起见,我在第 53 个有效数字后面加了空格。有点难数,使用编程打印的

十进制数我们可以四舍五入,二进制怎么办?

  • 精神是一样的:待处理部分有没有达到前一位的一半,达到就进位,没达到就舍去。(暂且当作 0 舍 1 入。)

那么我们的 0.1 在 double 中就是

0.00011001100110011001100110011001100110011001100110011001 10011...
0.00011001100110011001100110011001100110011001100110011010

而 1.1 就是

1.0001100110011001100110011001100110011001100110011001 10011...
1.0001100110011001100110011001100110011001100110011010

三、机器语言的加法

这个很简单,1.1 + 0.1 就是 1.2, 但是让我们看看机器如何相加↓:

  1.0001100110011001100110011001100110011001100110011010
+ 0.00011001100110011001100110011001100110011001100110011010
------------------------------------------------------------1.00110011001100110011001100110011001100110011001100111010

因为结果仍然是 double,需要再做一次保留 53 位有效数字和舍入:

1.0011001100110011001100110011001100110011001100110011 1010
1.0011001100110011001100110011001100110011001100110100

四、二进制转十进制的偏差

机器计算完成,机器需要转十进制给我们看

我们把最终结果转换回来:

1.0011001100110011001100110011001100110011001100110100

得到十进制的:

1.20000000000000018

一般的输出函数,在输出浮点数时,都会限制显示的有效数字,即会再做一次四舍五入。

**PS:**至于各个语言之间的差异,答案是可能会有,比如可能因为选择的舍入规则的不同可能导致的结果的不同;甚至有可能某个语言里的浮点数压根不是 IEEE 754 的浮点数,而是以字符串方式保存的,所以可能没有误差。

Double的输出

//使用BigDecimal
@Test
public void DoubleTest() {double testDoubleVal = 1.23456789;BigDecimal bigDecimal = new BigDecimal(testDoubleVal);System.out.println(bigDecimal.setScale(3, BigDecimal.ROUND_HALF_UP));System.out.println(bigDecimal.setScale(4, BigDecimal.ROUND_HALF_UP));//不同的舍入规则System.out.println(bigDecimal.setScale(4, BigDecimal.ROUND_DOWN));  //不同的舍入规则
}
/*
运算结果:1.2351.23461.2345
*/

double精度丢失问题相关推荐

  1. float与double精度丢失问题

    java中int,float,long,double取值范围 public class TestOutOfBound {public static void main(String[] args) { ...

  2. java long double精度丢失_long long类型转double类型部分精度丢失问题

    我最近做了一道题,一个64位(unsigned __int64)范围内的数输出其除以1000的值,并按四舍五入保留小数点后三位. 我刚开始直接写WA,结果发现当数比较大的时候,结果后几位精度总会丢失, ...

  3. Double计算精度丢失(金融入门知识点)

    Double计算精度丢失(金融入门知识点) 一.double精度丢失 二.为什么double会精度丢失 三.BigDecimal错误的用法 四.BigDecimal正确的用法 Double计算精度丢失 ...

  4. 对不起, 老师 我把知识还给您了 呜呜呜 ......面试杀手-double精度问题深入剖析 进制转换

    面试杀手-double精度问题 & 进制转换 场景模拟 先来看一段VCR (哦走错片场了- 是场景) 面试官: 请你打开IDEA 输出12.56 + 11.25的结果 我: 先愣了一会 啥也没 ...

  5. java中double类型精度丢失问题及解决方法

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源: https://blog.csdn.net/yacolsp ...

  6. float,double等精度丢失问题

    来自MSDN的解释: http://msdn.microsoft.com/zh-cn/c151dt3s.aspx 为何浮点数可能丢失精度浮点十进制值通常没有完全相同的二进制表示形式. 这是 CPU 所 ...

  7. double operator[](int i)_java中double类型精度丢失问题及解决方法

    原文链接:https://blog.csdn.net/yacolspace/article/details/78287394 double类型数据加减操作精度丢失问题 今天在项目中用到double类型 ...

  8. [ JAVA编程 ] double类型计算精度丢失问题及解决方法

    [ JAVA编程 ] double类型计算精度丢失问题及解决方法 参考文章: (1)[ JAVA编程 ] double类型计算精度丢失问题及解决方法 (2)https://www.cnblogs.co ...

  9. (金融入门知识点)Double类型丢失精度

    Double计算精度丢失原因:Double计算精度丢失(金融入门知识点)__yosemite的博客-CSDN博客_double精度丢失 Double计算精度丢失解决办法:Double类型丢失精度的两种 ...

  10. js前端double无法显示,long精度丢失,layUI数据表格

    一开始我是以对象形式把数据从后台返回到前端,追踪发现从后台返回了有两条数据,但是前端只显示了一条数据,如图. {"code":0,"count":2," ...

最新文章

  1. 【Linux】延时函数sleep、usleep、nanosleep、select、pselect的比较
  2. bert模型图解 很详细的与其他模型对比实验
  3. 适用于WIFI Hacking的无线网卡推荐
  4. Android-实现切换Fragment页功能
  5. Python Django 搭建纯净IP地址返回服务(返回访问者IP地址)
  6. MySQL创建和操纵数据库和表(DDL)最全总结(小白都能能懂哦)
  7. Python3实现红黑树[下篇]
  8. int mysql_「MYSQL」MYSQL中的int(11)到底代表什么意思?
  9. python蟒蛇绘制步骤_如何用python绘制蟒蛇移动的样子-百度经验
  10. 2.WindowsServer2012R2装完的一些友好化设置
  11. 浅析Hibernate映射(五)——集合映射
  12. Python爬虫:浅谈【破解某易云音乐加密-JS逆向】
  13. ASP.NET2.0 ReportingServices,报表灵魂的收割者(一)
  14. win10专业版安装
  15. 关于ES6中let 和 const 命令的用法以及注意事项:
  16. Java成员方法getinfo_成员方法
  17. springboot Activiti6
  18. 产品入库更新生产任务单工时
  19. 【无标题】XGPON和XGSPON MA5800 三方兼容
  20. TFS30063 您没有权限

热门文章

  1. 视图,触发器,事务,存储过程,函数与流程控制,索引
  2. DEV控件ASPxTextBox设置ClientEnabled=false之后出现的问题
  3. Oracle 11.2.0.4.0 Dataguard部署和日常维护(6)-Active Dataguard篇
  4. 记录一下----关于设计模式和面向对象设计原则
  5. Ajax关于readyState和status的讨论
  6. WPF/Silverlight 控件的几幅继承关系图
  7. Security+ 学习笔记50 取证技术
  8. Security+ 学习笔记4 社会工程攻击
  9. 重拾React: React 16.0
  10. EOJ 306 树上问题