Java中浮点数的处理

来源:互联网 发布:2016qq邮件钓鱼源码 编辑:程序博客网 时间:2024/05/09 11:18

1、介绍
2、格式化浮点数
3java.math.BigDecimal
 

 


 

1、介绍

      在Java中float和double类型的数据,无法精确表示计算结果。这是由于float和double是不精确的计算。
      例:
        System.out.println(0.05+0.01);
        System.out.println(1.0-0.42);
        System.out.println(4.015*100);
        System.out.println(123.3/100);
        System.out.println(0.05);
      得到如下结果:
        0.060000000000000005
        0.5800000000000001
       401.49999999999994
       1.2329999999999999

      如何实现浮点数字的精确计算,下面从2个方面讨论,一是从四舍五入,二是从使用BigDecimal工具类来实现精确计算。

 

2、格式化浮点数

    1)Math.round()

         Math类中的round方法实现的四舍五入无法精确到小数,如果经过×100的计算后再四舍五入还是没有办法保证得到精确的结果。

     2)java.text.DecimalFormat
 
          DecimalFormat可以按照一定的格式格式化数字,常用的格式化字符是#、0等。
          例:
            System.out.println(new java.text.DecimalFormat("0.00").format(3.125));
            System.out.println(new java.text.DecimalFormat("0.00").format(3.135));
        
但是得到的结果是:
           3.12
           3.14
        
这是因为DecimalFormat是使用half-even 舍入(
ROUND_HALF_EVEN),简单的说就是向当四舍五入的5的时候向最近的偶数靠。
  所以使用DecimalForamt也无法得到可靠的浮点数。
 
3java.math.BigDecimal
 
BigDecimal提供的一个不变的、任意精度的有符号十进制数对象,可以用它来实现浮点数的精确计算。
 
1)构造函数说明
 
BigDecimal提供了多个构造函数,和浮点数有关的有:
         BigDecimal(double val)  Translates a double into a BigDecimal.
         BigDecimal(String val)   Translates the String repre sentation of a BigDecimal into a BigDecimal.
     
但是用double参数来创建对象得到不精确的值,只有通过String来创建对象。
     
例:
        BigDecimal bd1=new BigDecimal(0.05);
        System.out.println(bd1.toString());
        BigDecimal bd2=new BigDecimal("0.05");
        System.out.println(bd2.toString());
   
得到结果:
        0.05000000000000000277555756156289135105907917022705078125

        0.05
   
所以,需要使用String来创建对象,如果是double数,可以先转为String
 
2)基本计算
 
    利用BigDecimal
 add      
加法
 subtract  
减法
 multiply   
乘法
 divide    
除法
 setscale  
四舍五入下面程序说明基本计算的方法
 
    //以下代码使用java.math.BigDecimal来实现浮点数的精确计算
        //+
        BigDecimal bd3=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd4=new BigDecimal(String.valueOf(0.01));
        System.out.println((bd3.add(bd4)).doubleValue());
       
        //-
        BigDecimal bd5=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd6=new BigDecimal(String.valueOf(0.01));
        System.out.println((bd5.subtract(bd6)).doubleValue());
       
        //*
        BigDecimal bd7=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd8=new BigDecimal(String.valueOf(0.01));
        System.out.println((bd7.multiply(bd8)).doubleValue());
       
        ///这里没有考虑数据错误的可能情况
        //定义了精确位数
        int scale=10;
        BigDecimal bd9=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd10=new BigDecimal(String.valueOf(0.03));
     
System.out.println((bd9.divide(bd10,scale,BigDecimal.ROUND_HALF_EVEN)).doubleValue());
       
        //四舍五入
        scale=4;
        BigDecimal bd11=new BigDecimal(String.valueOf(3.1415926));  
      
System.out.println(bd11.setScale(scale,BigDecimal.ROUND_HALF_DOWN).toString());

       在程序中多次用到了BigDecimal的精确模式这个参数,下面说明如下:

ROUND_CEILING
      
Rounding mode to round towards positive infinity.
      
向正无穷方向舍入

    ROUND_DOWN
       Rounding mode to round towards zero.
      
向零方向舍入
    ROUND_FLOORRounding mode to round towards negative infinity.
      

      
向负无穷方向舍入
    ROUND_HALF_DOWN
       Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
      
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
   
ROUND_HALF_EVEN
       Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor.
      
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用ROUND_HALF_DOWN 
    ROUND_HALF_UP
       Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
      
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
   
ROUND_UNNECESSARYRounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.
      

      
计算结果是精确的,不需要舍入模式
    ROUND_UP
       Rounding mode to round away from zero.
      
向远离0的方向舍入
    

下面是本文的示例代码:

        System.out.println(0.05+0.01);
        System.out.println(
1.0-0.42);
        System.out.println(
4.015*100);
        System.out.println(
123.3/100);
        System.out.println(
0.05);
        
        
//可以利用DecimalFormat类来格式化浮点数,但是得到的结果也有可能是错误的值
        System.out.println(new java.text.DecimalFormat("0.00").format(3.125));
        System.out.println(
new java.text.DecimalFormat("0.00").format(3.135));       
        
        
//以下代码是java.math.BigDecimal的构造函数
        BigDecimal bd1=new BigDecimal(0.05);
        System.out.println(bd1.toString());
        BigDecimal bd2
=new BigDecimal("0.05");
        System.out.println(bd2.toString());
        
        
//以下代码使用java.math.BigDecimal来实现浮点数的精确计算
        
//+
        BigDecimal bd3=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd4
=new BigDecimal(String.valueOf(0.01));
        System.out.println((bd3.add(bd4)).doubleValue());
        
        
//-
        BigDecimal bd5=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd6
=new BigDecimal(String.valueOf(0.01));
        System.out.println((bd5.subtract(bd6)).doubleValue()); 
        
        
//*
        BigDecimal bd7=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd8
=new BigDecimal(String.valueOf(0.01));
        System.out.println((bd7.multiply(bd8)).doubleValue()); 
        
        
///这里没有考虑数据错误的可能情况
        
//定义了精确位数
        int scale=10
        BigDecimal bd9
=new BigDecimal(String.valueOf(0.05));
        BigDecimal bd10
=new BigDecimal(String.valueOf(0.03));
        System.out.println((bd9.divide(bd10,scale,BigDecimal.ROUND_HALF_EVEN)).doubleValue()); 
        
        
//四舍五入
        scale=4;
        BigDecimal bd11
=new BigDecimal(String.valueOf(3.1415926));
        System.out.println(bd11.setScale(scale,BigDecimal.ROUND_HALF_UP).toString());

得到的结果:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
0.05
3.12
3.14
0.05000000000000000277555756156289135105907917022705078125
0.05
0.06
0.04
5.0E-4
1.6666666667
3.1416

原创粉丝点击