首页天道酬勤bigdecimal类型比较(bigdecimal数组)

bigdecimal类型比较(bigdecimal数组)

admin 02-07 16:32 208次浏览

1 .引言

浮点型和双精度型的主要设计目标是为了科学计算和工程计算。 他们执行二进制浮点运算。 它是为了在广域的数值范围内提供更准确的快速近似计算而精心设计的。 但是,它们没有提供完全正确的结果,所以在需要正确结果的情况下不应该使用。 但是,业务计算通常要求结果的准确性,BigDecimal在这方面很有用。

请先看下面的代码

publicstaticvoidmain (字符串[ ] args ) {

system.out.println(0.20.1 );

system.out.println(0.3-0.1;

system.out.println(0.2*0.1;

system.out.println(0.3/0.1;

}

执行结果如下

我认为你错了,结果是这样的。 问题在哪里? 因为我们的计算机是二进制的。 浮点数不能用二进制形式准确表示。 我们的CPU显示浮点数由指数和尾数两部分组成。 这种表示方法一般会失去一定的精度,一些浮点数运算也会产生一定的误差。 例如,2.4的二进制表示不是准确的2.4。 反而最近的二进制显示为2.3999999999999999。 浮点数值实际上是通过特定的公式计算的。

实际上,java的float只用于科学计算和工程计算,很多商业计算一般使用java.math.BigDecimal类进行准确的计算。

2.BigDecimal结构方法

公共双精度(双精度)不建议将双精度表示形式转换为双精度*

公共二进制(intval )将int表示转换为二进制

公共bigdecimal (字符串值)将字符串表示形式转换为bigdecimal

为什么不推荐第一种构造方法呢? 看看例子吧

publicstaticvoidmain (字符串[ ] args ) {

bigdecimal bigdecimal=new bigdecimal (2;

bigdecimalbdouble=new bigdecimal (2.3;

bigdecimalbstring=new bigdecimal (' 2.3 );

system.out.println (' bigdecimal=' bigdecimal );

系统. out.println (b double=' b double );

system.out.println (' b string=' b string );

}

执行结果如下

为什么会发生这种事呢?

JDK说明:

1、参数类型为double的结构方法结果具有一定的不可预测的智力。 通过向Java写入新bigdecimal (0.1 )创建的bigdecimal可能正好等于0.1,但实际上等于0.1000000000005511231270218158340451000000 或者,在这种情况下,不能表示为有限长度的二进制小数。 因此,传递给构造方法的值表面上不会为0.1。

2、另一方面,String的构建方法是完全可预测的。 写入newBigDecimal('0.1 ' )时,将创建BigDecimal,它正好等于预期的0.1。 因此,通常建议优先使用String结构方法。

如果需要将double用作BigDecimal的源,请使用double.toString(double )将其转换为String,然后使用String构造方法,或者使用BigDecimal的静态

publicstaticvoidmain (字符串[ ] args ) {

bigdecimalbdouble1=bigdecimal.value of (2.3;

bigdecimalbdouble2=新bigdecimal (double.tostring ) 2.3 );

system.out.println (b double1=' b double1);

system.out.println (b double2=' b double2);

}

3.BigDecimal加减运算

常见的加法、减法、乘法、除法和BigDecimal类提供了相应的成员方法。

publicbigdecimaladd (bigdecimal value; //加法

公共二进制辅助

t(BigDecimal value); //减法

public BigDecimal multiply(BigDecimal value); //乘法

public BigDecimal divide(BigDecimal value); //除法

大概的用法如下

public static voidmain(String[] args) {

BigDecimal a= new BigDecimal("4.5");

BigDecimal b= new BigDecimal("1.5");

System.out.println("a + b =" +a.add(b));

System.out.println("a - b =" +a.subtract(b));

System.out.println("a * b =" +a.multiply(b));

System.out.println("a / b =" +a.divide(b));

}

运行结果

这里有一点需要注意的是除法运算divide.

BigDecimal除法可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

其实divide方法有可以传三个参数

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

第一参数表示除数, 二个参数表示小数点后保留位数,第三个参数表示舍入模式。

只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种:

ROUND_UP :向远离零的方向舍入。舍弃非零部分,并将非零舍弃部分相邻的一位数字加一。

ROUND_DOWN :向接近零的方向舍入。舍弃非零部分,同时不会非零舍弃部分相邻的一位数字加一,采取截取行为。

ROUND_CEILING :向正无穷的方向舍入。如果为正数,舍入结果同ROUND_UP一致;如果为负数,舍入结果同ROUND_DOWN一致。注意:此模式不会减少数值大小。

ROUND_FLOOR :向负无穷的方向舍入。如果为正数,舍入结果同ROUND_DOWN一致;如果为负数,舍入结果同ROUND_UP一致。注意:此模式不会增加数值大小。

ROUND_HALF_UP :向“最接近”的数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。如果舍弃部分>= 0.5,则舍入行为与ROUND_UP相同;否则舍入行为与ROUND_DOWN相同。这种模式也就是我们常说的我们的“四舍五入”。

ROUND_HALF_DOWN :向“最接近”的数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式。如果舍弃部分> 0.5,则舍入行为与ROUND_UP相同;否则舍入行为与ROUND_DOWN相同。这种模式也就是我们常说的我们的“五舍六入”。

ROUND_HALF_EVEN :向“最接近”的数字舍入,如果与两个相邻数字的距离相等,则相邻的偶数舍入。如果舍弃部分左边的数字奇数,则舍入行为与 ROUND_HALF_UP 相同;如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。注意:在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况,如果前一位为奇数,则入位,否则舍去。

ROUND_UNNECESSARY :断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

按照各自的需要,可传入合适的第三个参数。四舍五入采用 ROUND_HALF_UP

需要对BigDecimal进行截断和四舍五入可用setScale方法,例:

public static voidmain(String[] args) {

BigDecimal a= new BigDecimal("4.5635");

a= a.setScale(3, RoundingMode.HALF_UP); //保留3位小数,且四舍五入

System.out.println(a);

}

减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象

public static voidmain(String[] args) {

BigDecimal a= new BigDecimal("4.5");

BigDecimal b= new BigDecimal("1.5");

a.add(b);

System.out.println(a);//输出4.5. 加减乘除方法会返回一个新的BigDecimal对象,原来的a不变

}

4.BigDecimal比较大小

public static voidmain(String[] args) {

BigDecimal a= new BigDecimal(101);

BigDecimal b= new BigDecimal(111);//使用compareTo方法比较//注意:a、b均不能为null,否则会报空指针

if (a.compareTo(b) == -1) {

System.out.println("a小于b");

}if (a.compareTo(b) == 0) {

System.out.println("a等于b");

}if (a.compareTo(b) == 1) {

System.out.println("a大于b");

}if (a.compareTo(b) > -1) {

System.out.println("a大于等于b");

}if (a.compareTo(b) < 1) {

System.out.println("a小于等于b");

}

}

5.BigDecimal转String

public static voidmain(String[] args) {//浮点数的打印

System.out.println(new BigDecimal("10000000000").toString());//普通的数字字符串

System.out.println(new BigDecimal("100.000").toString());//去除末尾多余的0

System.out.println(new BigDecimal("100.000").stripTrailingZeros().toString());//避免输出科学计数法

System.out.println(new BigDecimal("100.000").stripTrailingZeros().toPlainString());

}

打印结果

用toString()方法输出的就是普通的数字字符串。

stripTrailingZeros()函数就是用于去除末尾多余的0的,

用toPlainString()函数代替toString(),避免输出科学计数法的字符串。

6.总结

商业计算使用BigDecimal。

尽量使用参数类型为String的构造函数。

BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。

UGUI实现ScrollView无限滚动效果HTML5-&text&存储成本降低80%!US3在海量数据归档存储下的成本优化技术实践【私有网络 UVPC】网络ACL简介
bigdecimal取整数部分(bigdecimal只保留整数) bigdecimal设置小数位数(bigdecimal的方法)
相关内容