我是靠谱客的博主 坦率蛋挞,最近开发中收集的这篇文章主要介绍Java大数据之BigDecimal,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、和BigInteger的区别

整型大数据:BigInteger
浮点型大数据:BigDecimal

二、常量

BigDecimal num0=BigDecimal.ZERO;//0
BigDecimal num1=BigDecimal.ONE;//1
BigDecimal num10=BigDecimal.TEN;//10

三、初始化

1.字符串String做参数
BigDecimal a =new BigDecimal(“0.1”);
输出:0.1
2.数字double做参数
BigDecimal a =new BigDecimal(0.1);
输出:0.1000000000000000055511151231257827021181583404541015625

而:
BigDecimal a =new BigDecimal(0.5);
输出:0.5
不知道为啥(…,还望热心网友解答!

注意:最好用String做参数的原因:

1.0.1 无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.12.String 构造方法是完全可预知的:写入 new BigDecimal(0.1) 将创建一个BigDecimal,它正好等于预期的 0.13.floatdouble类型主要是为了科学计算和工程计算而设计,他们执行二进制浮点运算,二进制不能准确的表示一个小数,就像十进制不能准确的表示1/3,1/6等。

另一种说法:

我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。
我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。
如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。
浮点数的值实际上是由一个特定的数学公式计算得到的。

所以,通常情况下,我们会使用String对象作为参数来构造一个精确的BigDecimal对象。下面提供的三种方法都可以:

//方法一
BigDecimal a= new BigDecimal("1.1");
//方法二
BigDecimal b= new BigDecimal(Double.toString(1.1));
//方法三
BigDecimal c= BigDecimal.valueOf(1.1);

System.out.println(a);
System.out.println(b);
System.out.println(c);

运行结果:
1.1
1.1
1.1

BigDecimal.value(double val)方法为什么可以呢?
看看下面的源码,大家应该就清楚了:

public static BigDecimal valueOf(double val) {
  return new BigDecimal(Double.toString(val));
 }

四、常用方法

	public static void main(String[] args) {

		// 尽量用字符串的形式初始化
		BigDecimal num1 = new BigDecimal("5");
		BigDecimal num2 = new BigDecimal("17");
		BigDecimal num3 = new BigDecimal("100");

		// 加法
		BigDecimal add = num1.add(num2);
		// 减法
		BigDecimal subtract = num1.subtract(num2);
		// 乘法
		BigDecimal multiply = num1.multiply(num2);
		// 除法
		BigDecimal divide = num2.divide(num1, 7, BigDecimal.ROUND_HALF_UP);
		// 取余方法一
		BigDecimal mod1 = num1.remainder(num2);
		// 取余方法二
		BigDecimal[] mod2 = num1.divideAndRemainder(num2);
		// 绝对值
		BigDecimal abs = num3.abs();
		// 相反数
		BigDecimal negate = num3.negate();

		System.out.println("加法用string结果:" + add);

		System.out.println("减法用string结果:" + subtract);

		System.out.println("乘法用string结果:" + multiply);

		System.out.println("除法用string结果:" + divide);

		System.out.println("取余方法一用string结果:" + mod1);
		System.out.println("取余方法二用string结果:" + mod2[1]);// 注:mod2[0]是商

		System.out.println("绝对值用string结果:" + abs);

		System.out.println("相反数用string结果:" + negate);
	}

五、除法操作

除法操作有需要注意的地方,下面单独拿来说:
情况一:
结果是有限小数
eg:15/3 15/4

public static void main(String[] args) {
    BigDecimal a = new BigDecimal("15");
	BigDecimal b=new BigDecimal("3");
	BigDecimal divide=a.divide(b);
	System.out.println(divide);
}

结果正确
情况二:
结果是无限小数,如果还是按上面方法计算的话,会报错: Non-terminating decimal expansion; no exact representable decimal result.
eg:15/9

public static void main(String[] args) {
    BigDecimal a = new BigDecimal("15");
	BigDecimal b=new BigDecimal("9");
	BigDecimal divide=a.divide(b);
	System.out.println(divide);
}

结果错误为什么会报这种错呢??
原来JAVA中如果用BigDecimal做除法的时候一定要在divide方法中传递第二个参数,定义精确到小数点后几位,否则在不整除的情况下,结果是无限循环小数时,就会抛出以上异常。

怎样解决不整除仍能出现结果的情况呢,这时候就要传进去几个参数
方法一:BigDecimal构造方法
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode);
第一参数:除数
第二个参数:小数点后保留的位数
第三个参数:舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种:

ROUND_CEILING    //向正无穷方向舍入

ROUND_DOWN    //向零方向舍入

ROUND_FLOOR    //向负无穷方向舍入

ROUND_HALF_DOWN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5

ROUND_HALF_EVEN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN

ROUND_HALF_UP    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6

ROUND_UNNECESSARY    //计算结果是精确的,不需要舍入模式

ROUND_UP    //向远离0的方向舍入

代码:

public static void main(String[] args) {
    BigDecimal a = new BigDecimal("15");
    BigDecimal b=new BigDecimal("3");
	BigDecimal divide=a.divide(b,2,BigDecimal.ROUND_HALF_UP);
	System.out.println(divide);
}

运行截图:
1
方法二:setScale方法
代码:

public static void main(String[] args) {
	BigDecimal a = new BigDecimal("15");
	BigDecimal b=new BigDecimal("3");
	BigDecimal divide=a.divide(b);
	BigDecimal ans=divide.setScale(2, BigDecimal.ROUND_HALF_UP);
	System.out.println(ans);
}

运行截图:
2
注意+强调:

public static void main(String[] args) {
        BigDecimal a = new BigDecimal("15");
		BigDecimal b1=new BigDecimal("4");
		BigDecimal b2=new BigDecimal("7");
		
		BigDecimal divide1=a.divide(b1);
		BigDecimal ans1=divide1.setScale(1, BigDecimal.ROUND_HALF_UP);
		System.out.println(ans1);
		
		BigDecimal divide2=a.divide(b2);
		BigDecimal ans2=divide2.setScale(1, BigDecimal.ROUND_HALF_UP);
		System.out.println(ans2);
	}

在这里插入图片描述

总之,第五个大标题除法操作,主要讲的是两种情况:
相除结果是有限小数、相除结果是无限小数(不能说成这两种情况:能被整除、不能被整除 因为15/4不能被整除,但是也可以运行出结果)
1.相除结果是有限小数:
可以通过构造方法或者setScale方法来输出结果。
2.相除结果是无限小数:
要想运行出结果就必须设置参数,即public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode);`

附:
setScale使用注意:
代码1:

public static void main(String[] args) {
    BigDecimal a = new BigDecimal("15");
	BigDecimal b2=new BigDecimal("7");

	BigDecimal divide2=a.divide(b2);
	BigDecimal ans2=divide2.setScale(1, BigDecimal.ROUND_HALF_UP);
	System.out.println(ans2);
}

运行报错,因为setScale(1, BigDecimal.ROUND_HALF_UP)之前得到的divide2是无限小数。

代码2:

public static void main(String[] args) {
        BigDecimal a = new BigDecimal("15");
		BigDecimal b2=new BigDecimal("7");
		
		BigDecimal divide2=a.divide(b2,1,BigDecimal.ROUND_HALF_UP);
		BigDecimal ans2=divide2.setScale(0, BigDecimal.ROUND_HALF_UP);
		System.out.println(divide2);
		System.out.println(ans2);
	}

在这里插入图片描述

最后

以上就是坦率蛋挞为你收集整理的Java大数据之BigDecimal的全部内容,希望文章能够帮你解决Java大数据之BigDecimal所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部