今天刷面试题时,看到了(精度丢失)这个问题,今天来通过参考资料,把它总结一下


目录

  • ①<精度丢失>长什么样?
  • ②为什么会精度丢失?
  • ③用BigDecimal类解决精度丢失的问题

①<精度丢失>长什么样?

运行代码:

public static void main(String[] args) {System.out.println(2.0-1.1);
}

运行结果:

是的运行结果是0.8999999999999999,而不是你想的0.9;这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中,无法精确的表示分数1/10,就像是十进制无法精确的标识1/3(0.333333…)一样


②为什么会精度丢失?

使用代码:System.out.println(4.0 - 3.6);
运行结果:0.3999999999999999

计算过程解析:
注意:浮点数值采用二进制系统表示,而在二进制系统中,无法精确的表示分数1/10

  • 将十进制的 4.0 转换成 二进制,将十进制的 3.6 转换成二进制;
    4.0转为二进制:100
    3.6转二进制:11.100110011001…(一直循环除不尽)
  • 使用转换后的二进制,进行减法运算

3.6 转换成二进制,就类似于 1除以3一样,是除不尽。所以 System.out.println(4.0 - 3.6); 就会输出 0.3999999999999999


③用BigDecimal类解决精度丢失的问题

BigDecimal工具包:

/*** 用于高精确处理常用的数学运算*/
public class ArithmeticUtils {//默认除法运算精度private static final int DEF_DIV_SCALE = 10;/*** 提供精确的加法运算** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static double add(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.add(b2).doubleValue();}/*** 提供精确的加法运算** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static BigDecimal add(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.add(b2);}/*** 提供精确的加法运算** @param v1 被加数* @param v2 加数* @param scale 保留scale 位小数* @return 两个参数的和*/public static String add(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的减法运算** @param v1 被减数* @param v2 减数* @return 两个参数的差*/public static double sub(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.subtract(b2).doubleValue();}/*** 提供精确的减法运算。** @param v1 被减数* @param v2 减数* @return 两个参数的差*/public static BigDecimal sub(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.subtract(b2);}/*** 提供精确的减法运算** @param v1 被减数* @param v2 减数* @param scale 保留scale 位小数* @return 两个参数的差*/public static String sub(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static double mul(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.multiply(b2).doubleValue();}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static BigDecimal mul(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.multiply(b2);}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @param scale 保留scale 位小数* @return 两个参数的积*/public static double mul(double v1, double v2, int scale) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return round(b1.multiply(b2).doubleValue(), scale);}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @param scale 保留scale 位小数* @return 两个参数的积*/public static String mul(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到* 小数点以后10位,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @return 两个参数的商*/public static double div(double v1, double v2) {return div(v1, v2, DEF_DIV_SCALE);}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指* 定精度,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @param scale 表示表示需要精确到小数点以后几位。* @return 两个参数的商*/public static double div(double v1, double v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指* 定精度,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @param scale 表示需要精确到小数点以后几位* @return 两个参数的商*/public static String div(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v1);return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的小数位四舍五入处理** @param v  需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static double round(double v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b = new BigDecimal(Double.toString(v));return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供精确的小数位四舍五入处理** @param v  需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static String round(String v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b = new BigDecimal(v);return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 取余数** @param v1 被除数* @param v2 除数* @param scale 小数点后保留几位* @return 余数*/public static String remainder(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 取余数 BigDecimal** @param v1 被除数* @param v2 除数* @param scale 小数点后保留几位* @return 余数*/public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);}/*** 比较大小* 阿里巴巴开发规范明确:比较BigDecimal的等值需要使用compareTo,不可用equals* equals会比较值和精度,compareTo会忽略精度* @param v1 被比较数* @param v2 比较数* @return 如果v1 大于v2 则 返回true 否则false*/public static boolean compare(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);int bj = b1.compareTo(b2);boolean res;if (bj > 0)res = true;elseres = false;return res;}
}

使用工具包运算:


解决精度丢失问题~


参考:
Java用BigDecimal类解决Double类型精度丢失的问题
Java为什么会出现精度丢失这种现象你知道吗

关于double与float精度丢失问题~看完我明白了☆相关推荐

  1. double java 精度丢失_java中double和float精度丢失问题及解决方法

    在讨论两位double数0.2和0.3相加时,毫无疑问他们相加的结果是0.5.但是问题总是如此吗? 下面我们让下面两个doubles数相加,然后看看输出结果: @Test public void te ...

  2. BigDecimal操作double、float精度丢失问题

    一.问题 最近使用BigDecimal进行数值加减运算的时候踩了一个小坑:BigDecimal操作double.float数值时精度丢失. 举个例子: public static void main( ...

  3. mysql的double和float精度丢失问题

    经过测试,长度过长时     float类型,mysql会优先保留6位有效数字,对右侧的数字进行四舍五入:     double类型,mysql会优先保留16位有效数字,对右侧的数字进行四舍五入.

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

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

  5. 【c++】double转int精度丢失问题

    #include <iostream>int main() {double a = 74.49;int b = a * 100;std::cout << "a: &q ...

  6. 不愿意和别人打交道_不想麻烦别人,也不希望别人麻烦我,是什么心理?看完就明白...

    阅读本文前,请您先点击上面的"蓝色字体",再点击"关注",这样您就可以继续免费收到文章了.每天都有分享,完全是免费订阅,请放心关注. 注:本文转载自网络,侵删 ...

  7. 医院计算机管理在品管圈中的应用,品管圈在医院管理中怎么用?看完就明白了...

    原标题:品管圈在医院管理中怎么用?看完就明白了 品管圈(Quality Circle,QCC),又称"质量小组",是一种企业对基层员工的自主管理.全员品管及持续改善最佳的管理活动, ...

  8. android重置系统,安卓手机越用越卡,恢复出厂设置真有用?别瞎搞,看完就明白了!...

    安卓手机越用越卡,恢复出厂设置真有用?别瞎搞,看完就明白了! 现在手机的价格逐渐的开始上升,一部好一点的手机价格还是比较贵的,所以很多人想要节省更多的换机支出,都会想要购买到一款可以使用的比较久的手机 ...

  9. android8卡顿,看完就明白为什么安卓手机卡顿,这个技巧教你解决卡顿

    原标题:看完就明白为什么安卓手机卡顿,这个技巧教你解决卡顿 Android由源代码开放,所以安卓手机拥有更多的黑科技功能.很多安卓用户觉得手机卡顿,其实是没有好好利用这些神奇功能.下面笔者就为大家介绍 ...

最新文章

  1. 《树莓派开发实战(第2版)》——1.15 使用蓝牙设备
  2. Node.js v0.10版本发布
  3. 基于Foursquare, 我们还能做什么 ?
  4. python代码画皮卡丘_程序员式优雅表白,教你用python代码画爱心
  5. ipados 文件 连接服务器,iPadOS更新指南,总有一个功能是你需要的
  6. websocket文档_WebSocket推送 原理扫盲到上手实践
  7. Scrapy安装报错
  8. 程序员都该懂的 UML 规范!
  9. Q93:PLY文件对应图形法向量反向问题——以bunny10K为例
  10. Linux中KVM虚拟机是什么
  11. Atitit. BigConfirmTips 控件 大数据量提示确认控件的原理and总结O9
  12. python 绝对值计算
  13. java 商品库存修改
  14. python 基础-----list查找重复值
  15. Clickhouse除数为0
  16. Day08-整合富文本编辑器-p115
  17. 高性能图片服务器–ZIMG
  18. Malloc源码解读三——Bins与Arena
  19. COGS——T 1786. 韩信点兵
  20. 快速阅读等三种读书方法

热门文章

  1. java 熔断机制_利用Spring Cloud实现微服务- 熔断机制
  2. 浅谈国内图形学教育现状
  3. WIN10笔记本电脑任务栏wifi图标消失
  4. VBA知识:Like运算符详解
  5. 【标准】:ISO26262
  6. 应届生看过来 别以为没交社保就稳妥了
  7. G1 GC 并行参数解读
  8. 实力再获认可! 华为云Web应用防火墙进入国内主流安全产品名录
  9. C语言--爱因斯坦谜题
  10. python字母表顺序向后偏移3,python3:完全字母顺序