JAVA中浮点数的处理

来源:互联网 发布:淘宝最近查的严 编辑:程序博客网 时间:2024/05/14 15:44

1、介绍
2、格式化浮点数
3、Java.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也无法得到可靠的浮点数。

3、java.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());

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 0
原创粉丝点击