java⼩数乘法_JAVABigDecimal详解加减乘除⼩数舍⼊模式java.math.BigDecimal
概述
Java在java.math包中提供的API类BigDecimal,⽤来对超过16位有效位的数进⾏精确的运算。
双精度浮点型变量double可以处理16位有效数,但在实际应⽤中,可能需要对更⼤或者更⼩的数进⾏运算和处理。⼀般情况下,对于那些不需要准确计算精度的数字,我们可以直接使⽤Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中.
如果我们需要精确计算的结果,则必须使⽤BigDecimal类来操作。
B igDecimal所创建的是对象,故我们不能使⽤传统的+、-、*、/ 等算术运算符直接对其对象进⾏数学运算,⽽必须调⽤其相对应的⽅法。⽅法中的参数也必须是BigDecimal的对象。构造器是类的特殊⽅法,专门⽤来创建对象,特别是带有参数的对象。
BigDecimal常⽤构造函数
BigDecimal(int)
创建⼀个具有参数所指定整数值的对象
BigDecimal(double)
创建⼀个具有参数所指定双精度值的对象
BigDecimal(long)
创建⼀个具有参数所指定长整数值的对象
BigDecimal(String) 常⽤
创建⼀个具有参数所指定以字符串表⽰的数值的对象
使⽤⽰例:
BigDecimal a =new BigDecimal(0.1);
System.out.println("a values is:"+a);
System.out.println("=====================");
BigDecimal b =new BigDecimal("0.1");
System.out.println("b values is:"+b);
结果⽰例:
a values is:0.1000000000000000055511151231257827021181583404541015625
=====================
b values is:0.1
原因分析:
1)参数类型为double的构造⽅法的结果有⼀定的不可预知性。有⼈可能认为在Java中写⼊newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(⾮标度值 1,其标度为 1),但是它实际上等于
0.1000000000000000055511151231257827021181583404541015625。这是因为0.1⽆法准确地表⽰为 double(或者说对于该情况,不能表⽰为任何有限长度的⼆进制⼩数)。这样,传⼊到构造⽅法的值不会正好等于 0.1(虽然表⾯上等于该值)。
2)String 构造⽅法是完全可预知的:写⼊ newBigDecimal(“0.1”) 将创建⼀个 BigDecimal,它正好等于预期的 0.1。因此,⽐较⽽
3)当double必须⽤作BigDecimal的源时,请注意,此构造⽅法提供了⼀个准确转换;它不提供与以下操作相同的结果:先使⽤String(double)⽅法,然后使⽤BigDecimal(String)构造⽅法,将double转换为String。要获取该结果,请使⽤static valueOf(double)⽅法。
BigDecimal常⽤⽅法详解
常⽤⽅法
add(BigDecimal)
BigDecimal对象中的值相加,返回BigDecimal对象
subtract(BigDecimal)
BigDecimal对象中的值相减,返回BigDecimal对象
multiply(BigDecimal)
BigDecimal对象中的值相乘,返回BigDecimal对象
divide(BigDecimal)
BigDecimal对象中的值相除,返回BigDecimal对象
toString()
将BigDecimal对象中的值转换成字符串
doubleValue()
将BigDecimal对象中的值转换成双精度数
floatValue()
将BigDecimal对象中的值转换成单精度数
longValue()
将BigDecimal对象中的值转换成长整数
intValue()
将BigDecimal对象中的值转换成整数
除法特记:
public BigDecimal divide( BigDecimal divisor, int scale, int roundingMode);
divisor 除数, scale 精确⼩数位, roundingMode 舍⼊模式
BigDecimal的8种舍⼊模式
BigDecimal resVal = new BigDecimal("0");
舍⼊⽅法:setScale(0,BigDecimal.ROUND_UP)第⼀个参数0表⽰舍⼊之后的⼩数位数,第⼆个参数表⽰舍⼊⽅式
1、ROUND_UP向上取整(正负远离零的舍⼊模式)
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_UP);
结果:24
BigDecimal bdNum = new BigDecimal("-23.3693");
结果:-24
2、ROUND_DOWN向下取整(正负接近零的舍⼊模式)
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_DOWN);
结果:23
BigDecimal bdNum = new BigDecimal("-23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_DOWN);
结果:-23
3、ROUND_CEILING向⼤取整(⽐原数值⼤的⽅向) 如果 BigDecimal 为正,则舍⼊⾏为与 ROUND_UP 相同; 如果为负,则舍⼊⾏为与ROUND_DOWN 相同。
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_CEILING);
结果:24
BigDecimal bdNum = new BigDecimal("-23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_CEILING);
结果:-23
4、ROUND_FLOOR向⼩取整(⽐原数值⼩的⽅向)如果 BigDecimal 为正,则舍⼊⾏为与 ROUND_DOWN 相同; 如果为负,则舍⼊⾏为与ROUND_UP 相同。
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_FLOOR);
结果:23
BigDecimal bdNum = new BigDecimal("-23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_FLOOR);
结果:-24
5、ROUND_HALF_UP(四舍五⼊) 向“最接近的”数字舍⼊,如果舍弃部分 >= 0.5,则舍⼊⾏为与 ROUND_UP 相同;否则舍⼊⾏为与ROUND_DOWN 相同。
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_UP);
结果:23
BigDecimal bdNum = new BigDecimal("23.6693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_UP);
结果:24
BigDecimal bdNum = new BigDecimal("23.5");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_UP);
6、ROUND_HALF_DOWN(五舍六⼊) 向“最接近的”数字舍⼊,如果舍弃部分 <= 0.5,则舍⼊⾏为与 ROUND_DOWN 相同; 否则舍⼊⾏为与 ROUND_UP 相同。
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_DOWN);
结果:23
BigDecimal bdNum = new BigDecimal("23.6693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_DOWN);
结果:24
BigDecimal bdNum = new BigDecimal("23.5");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_DOWN);
结果:23
7、ROUND_HALF_EVEN
向“最接近的”数字舍⼊,如果与两个相邻数字的距离相等,则向相邻的偶数舍⼊。 如果舍弃部分左边
的数字为奇数,则舍⼊⾏为与ROUND_HALF_UP 相同; 如果为偶数,则舍⼊⾏为与 ROUND_HALF_DOWN 相同。
bigdecimal除法保留小数四舍六⼊,五分两种情况。 如果前⼀位为奇数,则⼊位,否则舍去。
BigDecimal bdNum = new BigDecimal("23.3693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);
结果:23
BigDecimal bdNum = new BigDecimal("23.6693");
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);
结果:24
BigDecimal bdNum = new BigDecimal("23.5");// 如果与两个相邻数字的距离相等,则向相邻的偶数舍⼊
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);
结果:24
BigDecimal bdNum = new BigDecimal("22.5");// 如果与两个相邻数字的距离相等,则向相邻的偶数舍⼊
resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);
结果:22
8、ROUND_UNNECESSARY 断⾔请求的操作具有精确的结果,因此不需要舍⼊。 如果对获得精确结果的操作指定此舍⼊模式,则抛出ArithmeticException。
BigDecimal bdNum = new BigDecimal("22.3368");
resVal = bdNum.setScale(4, BigDecimal.ROUND_UNNECESSARY);
结果:22.3368
BigDecimal bdNum = new BigDecimal("22.3368");
resVal = bdNum.setScale(0, BigDecimal.ROUND_UNNECESSARY);
Exception in thread "main" java.lang.ArithmeticException: Rounding necessary
at java.math.BigDecimalmonNeedIncrement(BigDecimal.java:4148)
at java.dIncrement(BigDecimal.java:4204)
at java.math.BigDecimal.divideAndRound(BigDecimal.java:4112)
at java.math.BigDecimal.setScale(BigDecimal.java:2452)
ample.demo622.Demo622ApplicationTests.main(Demo622ApplicationTests.java:213)
BigDecimal 平⽅根
BigDecimal bdNum1 = new BigDecimal(String.valueOf(Math.sqrt(4)));
结果:2.0
BigDecimal 幂次⽅
BigDecimal res = new BigDecimal("3").pow(2); // 3的2次⽅
结果: res = 9;
BigDecimal⼤⼩⽐较
java中对BigDecimal⽐较⼤⼩⼀般⽤的是bigdemical的compareTo⽅法
BigDecimal a = new BigDecimal ("1");
BigDecimal b = new BigDecimal ("2");
int val = apareTo(b);
System.out.println(val);
返回结果分析:
val = -1,表⽰a⼩于b;
若 val = 0 ,表⽰a等于b;
若 val = 1 ,表⽰a⼤于b;
BigDecimal总结
6.1、总结
在需要精确的⼩数计算时再使⽤BigDecimal,BigDecimal的性能⽐double和float差,在处理庞⼤,复杂的运算时尤为明显。故⼀般精度的计算没必要使⽤BigDecimal。
尽量使⽤参数类型为String的构造函数。
BigDecimal都是不可变的(immutable)的, 在进⾏每⼀次四则运算时,都会产⽣⼀个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。
/**
* BigDecimal⾼精度数学计算
*/
public class ArithmeticUtils {
//默认除法运算精度
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论