全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

JAVA浮点数计算精度损失底层原理与解决方案

问题:

对两个double类型的值进行运算,有时会出现结果值异常的问题。比如:

  System.out.println(19.99+20);
  System.out.println(1.0-0.66);
  System.out.println(0.033*100);
  System.out.println(12.3/100);

输出:

39.989999999999995
0.33999999999999997
3.3000000000000003
0.12300000000000001

Java中的简单浮点数类型float和double不能够精确运算。这个问题其实不是JAVA的bug,因为计算机本身是二进制的,而浮点数实际上只是个近似值,所以从二进制转化为十进制浮点数时,精度容易丢失,导致精度下降。

关于精度损失的原理可以很简单的讲,首先一个正整数在计算机中表示使用01010形式表示的,浮点数也不例外。

比如11,11除以2等于5余1

       5除以2等于2余1

       2除以2等于1余0

       1除以2等于0余1

所以11二进制表示为:1011.

double类型占8个字节,64位,第1位为符号位,后面11位是指数部分,剩余部分是有效数字。

正整数除以2肯定会有个尽头的,之后二进制还原成十进制只需要乘以2即可。

举个例子:0.99用的有效数字部分,

       0.99 * 2 = 1+0.98 --> 1
       0.98 * 2 = 1+0.96 --> 1
       0.96 * 2 = 1+0.92 -- >1
       0.92 * 2 = 1+0.84 -- >1
         ...............

这样周而复始是没法有尽头的,而double有效数字有限,所以必定会有损失,所以二进制无法准确表示0.99,就像十进制无法准确表示1/3一样。

解决办法:

在《Effective Java》中提到一个原则,那就是float和double只能用来作科学计算或者是工程计算,但在商业计算中我们要用java.math.BigDecimal,通过使用BigDecimal类可以解决上述问题,首先需要注意的是,直接使用字符串来构造BigDecimal是绝对没有精度损失的,如果用double或者把double转化成string来构造BigDecimal依然会有精度损失,所以我觉得这种解决方法就是在使用中就把浮点数用string来表示存放,涉及到运算直接用string构造double,否则肯定会有精度损失。

1. 相加

/**
 * 相加
 * @param double1
 * @param double2
 * @return
 */
public static double add(String doubleValA, String doubleValB) { 
  BigDecimal a2 = new BigDecimal(doubleValA); 
  BigDecimal b2 = new BigDecimal(doubleValB); 
  return a2.add(b2).doubleValue(); 
}

2. 相减

/**
 * 相减
 * @param double1
 * @param double2
 * @return
 */
public static double sub(String doubleValA, String doubleValB) { 
  BigDecimal a2 = new BigDecimal(doubleValA); 
  BigDecimal b2 = new BigDecimal(doubleValB); 
  return a2.subtract(b2).doubleValue();
}

3. 相乘

/**
 * 相乘
 * @param double1
 * @param double2
 * @return
 */
public static double mul(String doubleValA, String doubleValB) { 
  BigDecimal a2 = new BigDecimal(doubleValA); 
  BigDecimal b2 = new BigDecimal(doubleValB); 
  return a2.multiply(b2).doubleValue();
}

4. 相除

/**
 * 相除
 * @param double1
 * @param double2
 * @param scale 除不尽时指定精度
 * @return
 */
public static double div(String doubleValA, String doubleValB, int scale) { 
  BigDecimal a2 = new BigDecimal(doubleValA); 
  BigDecimal b2 = new BigDecimal(doubleValB);
  return a2.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); 
}

5. 主函数调用

public static void main(String[] args) {
  String doubleValA = "3.14159267";
  String doubleValB = "2.358";
  System.out.println("add:" + add(doubleValA, doubleValB));
  System.out.println("sub:" + sub(doubleValA, doubleValB));
  System.out.println("mul:" + mul(doubleValA, doubleValB));
  System.out.println("div:" + div(doubleValA, doubleValB, 8));
}

结果展示如下所示:

 add:5.49959267
 sub:0.78359267
 mul:7.40787551586
 div:1.33231241

所以最好的方法是完全抛弃double,用string和java.math.BigDecimal。

java遵照IEEE制定的浮点数表示法来进行float,double运算。这种结构是一种科学计数法,用符号、指数和尾数来表示,底数定为2——即把一个浮点数表示为尾数乘以2的指数次方再添上符号。具体底层如何存储以及如何进行运行请继续关注我的博客,后续我会将详情总结好的。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# java  # 浮点数  # Java LinkedHashMap 底层实现原理分析  # 在java中ArrayList集合底层的扩容原理  # Java synchronize底层实现原理及优化  # Java CAS底层实现原理实例详解  # JAVA序列化和反序列化的底层实现原理解析  # JAVA字符串类型switch的底层原理详析  # Java并发底层实现原理学习心得  # Java集合的总体框架相关知识总结  # Java集合中contains方法的效率对比分析  # Java基础学习之集合底层原理  # 会有  # 的是  # 是个  # 也不  # 是一种  # 有个  # 就像  # 我觉得  # 正整数  # 最好的  # 相减  # 但在  # 这个问题  # 就把  # 很简单  # 要用  # 或者是  # 只需要  # 周而复始 


相关文章: 小说建站VPS选用指南:性能对比、配置优化与建站方案解析  c# 服务器GC和工作站GC的区别和设置  网站企业制作流程,用什么语言做企业网站比较好?  如何通过建站之星自助学习解决操作问题?  电商网站制作公司有哪些,1688网是什么意思?  青浦网站制作公司有哪些,苹果官网发货地是哪里?  如何通过VPS建站实现广告与增值服务盈利?  建站主机选择指南:服务器配置与SEO优化实战技巧  网站制作多少钱一个,建一个论坛网站大约需要多少钱?  Java解压缩zip - 解压缩多个文件或文件夹实例  移民网站制作流程,怎么看加拿大移民官网?  建站主机服务器选型指南与性能优化方案解析  公司门户网站制作流程,华为官网怎么做?  如何在IIS服务器上快速部署高效网站?  制作公司内部网站有哪些,内网如何建网站?  高性能网站服务器配置指南:安全稳定与高效建站核心方案  如何选择美橙互联多站合一建站方案?  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  一键制作网站软件下载安装,一键自动采集网页文档制作步骤?  小型网站建站如何选择虚拟主机?  建站之星如何快速生成多端适配网站?  湖州网站制作公司有哪些,浙江中蓝新能源公司官网?  图册素材网站设计制作软件,图册的导出方式有几种?  如何在服务器上三步完成建站并提升流量?  如何获取PHP WAP自助建站系统源码?  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  建站之星后台管理如何实现高效配置?  如何通过免费商城建站系统源码自定义网站主题与功能?  网站制作企业,网站的banner和导航栏是指什么?  北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?  建站主机选购指南:核心配置与性价比推荐解析  如何快速搭建安全的FTP站点?  韩国服务器如何优化跨境访问实现高效连接?  小型网站制作HTML,*游戏网站怎么搭建?  早安海报制作网站推荐大全,企业早安海报怎么每天更换?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  如何在万网自助建站中设置域名及备案?  ,石家庄四十八中学官网?  建站主机选哪种环境更利于SEO优化?  建站之星×万网:智能建站系统+自助建站平台一键生成  大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?  建站之星各版本价格是多少?  惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?  制作营销网站公司,淘特是干什么用的?  如何做网站制作流程,*游戏网站怎么搭建?  如何通过二级域名建站提升品牌影响力?  如何通过西部建站助手安装IIS服务器?  学校为何禁止电信移动建设网站?  制作证书网站有哪些,全国城建培训中心证书查询官网?  建站之星手机一键生成:多端自适应+小程序开发快速建站指南 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。