Java中如何解决double和float精度不准的问题

简介: 我们知道浮点数是无法在计算机中准确表示的,例如0.1在计算机中只是表示成了一个近似值,因此,对付点数的运算时结果具有不可预知性。在进行数字运算时,如果有double或float类型的浮点数参与计算,偶尔会出现计算不准确的情况。

我们知道浮点数是无法在计算机中准确表示的,例如0.1在计算机中只是表示成了一个近似值,因此,对付点数的运算时结果具有不可预知性。

在进行数字运算时,如果有double或float类型的浮点数参与计算,偶尔会出现计算不准确的情况。如以下示例代码:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package ex;  
  2.   
  3. public class BigDeciTest {  
  4.     public static void main(String[] args){  
  5.         System.out.println(0.05+0.01);  
  6.         System.out.println(1.0-0.42);  
  7.         System.out.println(4.015*100);  
  8.         System.out.println(123.3/100);  
  9.           
  10.     }  
  11.   
  12. }  
上述代码执行结果如下:

[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 0.060000000000000005  
  2. 0.5800000000000001  
  3. 401.49999999999994  
  4. 1.2329999999999999  

在大多数情况下,使用double和float计算的结果是准确的,但是在一些精度要求很高的系统中,这种问题是非常严重的。

在《Effective Java》中提到一个原则,那就是float和double只能用来作科学计算或者是工程计算,但在商业计算中我们要用java.math.BigDecimal,通过使用BigDecimal类我们可以解决上述问题,实例代码如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package ex;  
  2.   
  3. import java.math.*;  
  4.   
  5. public class BigDecimalDemo {  
  6.     public static void main(String[] args){  
  7.         System.out.println(ArithUtil.add(0.010.05));  
  8.         System.out.println(ArithUtil.sub(1.00.42));  
  9.         System.out.println(ArithUtil.mul(4.015100));  
  10.         System.out.println(ArithUtil.div(123.3100));  
  11.     }  
  12. }  
  13.   
  14. class ArithUtil{  
  15.     private static final int DEF_DIV_SCALE=10;  
  16.       
  17.     private ArithUtil(){}  
  18.       
  19.     public static double add(double d1,double d2){  
  20.         BigDecimal b1=new BigDecimal(Double.toString(d1));  
  21.         BigDecimal b2=new BigDecimal(Double.toString(d2));  
  22.         return b1.add(b2).doubleValue();  
  23.           
  24.     }  
  25.       
  26.     public static double sub(double d1,double d2){  
  27.         BigDecimal b1=new BigDecimal(Double.toString(d1));  
  28.         BigDecimal b2=new BigDecimal(Double.toString(d2));  
  29.         return b1.subtract(b2).doubleValue();  
  30.           
  31.     }  
  32.       
  33.     public static double mul(double d1,double d2){  
  34.         BigDecimal b1=new BigDecimal(Double.toString(d1));  
  35.         BigDecimal b2=new BigDecimal(Double.toString(d2));  
  36.         return b1.multiply(b2).doubleValue();  
  37.           
  38.     }  
  39.       
  40.     public static double div(double d1,double d2){  
  41.   
  42.         return div(d1,d2,DEF_DIV_SCALE);  
  43.           
  44.     }  
  45.       
  46.     public static double div(double d1,double d2,int scale){  
  47.         if(scale<0){  
  48.             throw new IllegalArgumentException("The scale must be a positive integer or zero");  
  49.         }  
  50.         BigDecimal b1=new BigDecimal(Double.toString(d1));  
  51.         BigDecimal b2=new BigDecimal(Double.toString(d2));  
  52.         return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  
  53.           
  54.     }  
  55.       
  56. }  

运行结果如下:

[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 0.06  
  2. 0.58  
  3. 401.5  
  4. 1.233  

详细,请参考API文档。

 

转自:http://blog.csdn.net/yinan9/article/details/17283081 

若转载请注明出处!若有疑问,请回复交流!
目录
相关文章
|
存储 关系型数据库 MySQL
double ,FLOAT还是double(m,n)--深入解析MySQL数据库中双精度浮点数的使用
本文探讨了在MySQL中使用`float`和`double`时指定精度和刻度的影响。对于`float`,指定精度会影响存储大小:0-23位使用4字节单精度存储,24-53位使用8字节双精度存储。而对于`double`,指定精度和刻度对存储空间没有影响,但可以限制数值的输入范围,提高数据的规范性和业务意义。从性能角度看,`float`和`double`的区别不大,但在存储空间和数据输入方面,指定精度和刻度有助于优化和约束。
2006 5
Java项目中高精度数值计算:为何BigDecimal优于Double
在Java项目开发中,涉及金额计算、面积计算等高精度数值操作时,应选择 `BigDecimal` 而非 `Double`。`BigDecimal` 提供任意精度的小数运算、多种舍入模式和良好的可读性,确保计算结果的准确性和可靠性。例如,在金额计算中,`BigDecimal` 可以精确到小数点后两位,而 `Double` 可能因精度问题导致结果不准确。
423 1
|
存储 C语言
使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小
【10月更文挑战第13天】使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小。
630 1
【Java基础面试十】、何对Integer和Double类型判断相等?
这篇文章讨论了如何在Java中正确比较`Integer`和`Double`类型的值,指出不能直接使用`==`操作符比较不同类型,而应该将它们转换为相同的基本数据类型(如`double`)后进行比较。
【Java基础面试十】、何对Integer和Double类型判断相等?
|
Java
Java中将保留四位小数的Double转换为String的方法详解
选择合适的方法,可以使代码更加简洁、高效,同时也能满足不同场景下的需求。
664 5
|
存储 编译器 C++
C++从遗忘到入门问题之float、double 和 long double 之间的主要区别是什么
C++从遗忘到入门问题之float、double 和 long double 之间的主要区别是什么
416 0
|
存储 SQL 数据库
MySQL设计规约问题之为何推荐用DECIMAL代替FLOAT和DOUBLE来存储精确浮点数
MySQL设计规约问题之为何推荐用DECIMAL代替FLOAT和DOUBLE来存储精确浮点数
|
Java
Java的double值保留2位小数
【6月更文挑战第16天】Java的double值保留2位小数
736 0
|
存储 Java
百度搜索:蓝易云【Java语言之float、double内存存储方式】
由于使用IEEE 754标准进行存储,float和double类型可以表示非常大或非常小的浮点数,并且具有一定的精度。然而,由于浮点数的特性,它们在进行精确计算时可能会存在舍入误差。在编写Java程序时,需要注意使
281 0
|
存储 C语言
C 语言实例 - 计算 int, float, double 和 char 字节大小
C 语言实例 - 计算 int, float, double 和 char 字节大小。
247 1