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的计算后再四舍五入还是没有办法保证得到精确的结果。
例:
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的时候向最近的偶数靠。
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
add 加法
subtract 减法
multiply 乘法
divide 除法
setscale 四舍五入 下面程序说明基本计算的方法
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( 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