Java中浮点数的处理

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值