文章目录
BigDecimal的介绍及使用场景
一、整理原因
是之前公司没有设计到金钱计算业务,现在应项目需要再做下学习和整理。金额计算不能用doube、float !!!金额计算必须用BigDecimal!!!!!!!!!!!!
二、 为什么要使用BigDecimal
因为涉及到钱的如果使用float 还是double在计算的时候会出现精度丢失,这是因为十进制值通常没有完全相同的二进制表示形式;十进制数的二进制表示形式可能不精确。只能无限接近于那个值。这样的话是不能忍受的!!不然我必须发财了。
三、简介
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的加、减、乘、除等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。
四、BigDecimal的构造器和方法初步认识
1.1构造器
- BigDecimal(int) 创建一个具有参数所指定整数值的对象。
- BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
- BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
- BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。 //推荐使用
1.2常用方法
- add(BigDecimal) BigDecimal对象中的值相加。
- subtract(BigDecimal) BigDecimal对象中的值相减。
- multiply(BigDecimal) BigDecimal对象中的值相乘。
- divide(BigDecimal) BigDecimal对象中的值相除。!!这里要注意取舍模式,否者会出现 java.lang.ArithmeticException。下面会给demo
- toString() 将BigDecimal对象的数值转换成字符串。
- doubleValue() 将BigDecimal对象中的值以双精度数返回。
- floatValue() 将BigDecimal对象中的值以单精度数返回。
- longValue() 将BigDecimal对象中的值以长整数返回。
- intValue() 将BigDecimal对象中的值以整数返回。
五、看看为什么不能用float 还是double
1.下面这个例子就什么了精度丢失
@Test
void testDouble() {
double a = 0.02;
double b = 0.03;
double c = b - a;
System.out.println(c);
}
本身想要的结果是0.01,但是结果确实0.009999999999999998。
六、demo以及使用场景
1.加减乘除初步体验
@Test
void testBigDecimalOperation() {
//推荐使用string类型的构造器
BigDecimal bigDecimal1 = new BigDecimal("1.02");
BigDecimal bigDecimal2 = new BigDecimal("2.02");
//加
System.out.println("加:"+bigDecimal1.add(bigDecimal2));
//减
System.out.println("减:"+bigDecimal1.subtract(bigDecimal2));
//乘
System.out.println("乘:"+bigDecimal1.multiply(bigDecimal2));
//除
System.out.println("除:"+bigDecimal1.divide(bigDecimal2,3,BigDecimal.ROUND_UP));
}
//结果
//加:3.04
//减:-1.00
//乘:2.0604
//除:0.505
2.大小比较 (CompareTon、Equals)
CompareTon方法(这里也推荐大家使用这种 )
@Test
void testBigDecimalCompareTon() {
//两个BigDecimal值比较使用compareTo方法, 比较结果有-1, 0, 1, 分别表示小于, 等于, 大于; 对于0, 可以使用BigDecimal.ZERO表示
BigDecimal bigDecimal1 = new BigDecimal("1.02");
BigDecimal bigDecimal2 = new BigDecimal("1.02");
//比较
System.out.println(bigDecimal1.compareTo(bigDecimal2));
//比较
bigDecimal2 = new BigDecimal("1.03");
System.out.println(bigDecimal1.compareTo(bigDecimal2));
//比较
bigDecimal2 = new BigDecimal("1.01");
System.out.println(bigDecimal1.compareTo(bigDecimal2));
//结果
//0
//-1
//1
}
这里再说说BigDecimalde Equals方法
@Test
void testBigDecimalEquals() {
//两个BigDecimal值比较使用compareTo方法, 比较结果有-1, 0, 1, 分别表示小于, 等于, 大于; 对于0, 可以使用BigDecimal.ZERO表示
BigDecimal bigDecimal1 = new BigDecimal("1");
BigDecimal bigDecimal2 = new BigDecimal("1.00");
//比较
System.out.println(bigDecimal1.equals(bigDecimal2));
//比较
bigDecimal2 = new BigDecimal("1.03");
System.out.println(bigDecimal1.equals(bigDecimal2));
//比较
bigDecimal2 = new BigDecimal("1.01");
System.out.println(bigDecimal1.equals(bigDecimal2));
//结果
//false
//false
//false
}
在使用BigDecimal的equals方法对1和1.00进行比较的时候,有的时候是true(当使用int、double定义BigDecimal时),有的时候是false(当使用String定义BigDecimal时)。equals方法和compareTo并不一样,equals方法会比较两部分内容,分别是值(value)和标度(scale)。(可以查下源码 )如下:
/**
* Compares this {@code BigDecimal} with the specified
* {@code Object} for equality. Unlike {@link
* #compareTo(BigDecimal) compareTo}, this method considers two
* {@code BigDecimal} objects equal only if they are equal in
* value and scale (thus 2.0 is not equal to 2.00 when compared by
* this method).
*
* @param x {@code Object} to which this {@code BigDecimal} is
* to be compared.
* @return {@code true} if and only if the specified {@code Object} is a
* {@code BigDecimal} whose value and scale are equal to this
* {@code BigDecimal}'s.
* @see #compareTo(java.math.BigDecimal)
* @see #hashCode
*/
@Override
public boolean equals(Object x) {
if (!(x instanceof BigDecimal))
return false;
BigDecimal xDec = (BigDecimal) x;
if (x == this)
return true;
if (scale != xDec.scale)
return false;
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {
if (xs == INFLATED)
xs = compactValFor(xDec.intVal);
return xs == s;
} else if (xs != INFLATED)
return xs == compactValFor(this.intVal);
return this.inflated().equals(xDec.inflated());
}
3.特别处理 相除
@Test
void testBigDecimalDivide() {
BigDecimal bigDecimal = new BigDecimal("50");
BigDecimal multiply = bigDecimal.multiply(new BigDecimal(0.09 / 1.001));
System.out.println(multiply);
//直接删除多余的小数位
System.out.println(multiply.setScale(2, BigDecimal.ROUND_DOWN));
//进位
System.out.println(multiply.setScale(2, BigDecimal.ROUND_UP));
//四舍五入 +1
System.out.println(multiply.setScale(2, BigDecimal.ROUND_HALF_UP));
//四舍五入 直接舍去
System.out.println(multiply.setScale(2, BigDecimal.ROUND_HALF_DOWN));
}
七、MySQL中的BigDecimal
BigDecimal在进行入库时, 数据库选择decimal类型, 长度可以自定义, 小数点我们项目中用的是2(看具体使用场景)默认0.00,千万不能是NULL, 否则在进行加减排序等操作时, 会带来转换的麻烦!
`balance` decimal(6,2) DEFAULT '0.00' COMMENT '账户余额',
`pirce` decimal(6,2) DEFAULT '0.00' COMMENT '单价',
大家有任何问题欢迎评论区留言 或者加qq邮箱:1435469553@qq.com