BigDecimal
B i g D e c i m a l BigDecimal BigDecimal 由任意精度的整数非标度值和 32 32 32 位的整数标度 ( s c a l e scale scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 10 10 的负 s c a l e scale scale 次幂。因此, B i g D e c i m a l BigDecimal BigDecimal 表示的数值是( unscaledValue*10-scale)。
二、构造函数
第一种:把 d o u b l e double double 转化为 B i g D e c i m a l BigDecimal BigDecimal
BigDecimal(double val);
第二种:把String转化为BigDecimal
BigDecimal(String val);
使用 B i g D e c i m a l BigDecimal BigDecimal 要用 S t r i n g String String 来够造,要做一个加法运算,需要先将两个浮点数转为 S t r i n g String String ,然后够造成 B i g D e c i m a l BigDecimal BigDecimal,在其中一个上调用 a d d add add 方法,传入另一个作为参数,然后把运算的结果( B i g D e c i m a l BigDecimal BigDecimal)再转换为浮点数。由于 d o u b l e double double 类型精度不够精确,若直接传入 d o u b l e double double 类型结果不会和预期相同,因此创建对象时使用String类型。
三、运算
BigDecimal add(BigDecimal val) //BigDecimal 加法
BigDecimal subtract (BigDecimal val) //BigDecimal 减法
BigDecimal multiply (BigDecimal val) //BigDecimal 乘法
BigDecimal divide (BigDecimal val, int scale, RoundingMode mode)
//除法,第二个参数是精度值,第三个参数是保留小数位的规则(比如四舍五入)。后面两个参数可以不传入,但是当出现无限循环小数时必须传入两个参数。一般情况是传入了第二个参数就得传入第三个参数,一般是BigDecimal.ROUND_HALF_UP。
加减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象
四、BigDecimal的setScale方法
B i g D e c i m a l . s e t S c a l e ( ) BigDecimal.setScale() BigDecimal.setScale() 方法用于格式化小数点,需要注意的是它不会直接在原对象上面发生改变,需要赋值到一个新的对象。
表示保留6位小数,用四舍五入方式:$BigDecimal b = a.setScale(6,BigDecimal.ROUND_HALF_UP) $
直接删除多余的小数位,如2.35会变成2.3: B i g D e c i m a l b = a . s e t S c a l e ( 1 , B i g D e c i m a l . R O U N D _ D O W N ) BigDecimal b = a.setScale(1,BigDecimal.ROUND\_DOWN) BigDecimalb=a.setScale(1,BigDecimal.ROUND_DOWN)
注意:
s c a l e scale scale 指的是小数点后的位数
s c a l e ( ) scale() scale() 就是 B i g D e c i m a l BigDecimal BigDecimal 类中的方法。如:
BigDecimal b = new BigDecimal("123.456");
b.scale(); //返回的就是3
五、舍入模式
- BigDecimal.Round_UP 远离零的舍入模式(向上舍入)。舍弃某部分时,若舍弃部分非零则对其前面的数字加1(此舍入模式始终不会减少计算值的大小)
0.833333… → 0.83334
- BigDecimal.Round_DOWN 接近零的舍入模式(向下舍入)。直接丢弃需舍弃部分(此舍入模式始终不会增加计算值的大小)
0.833333… → 0.83333
- BigDecimal.Round_CEILING 接近正无穷大的舍入模式。若BigDecimal为正,则舍入行为同ROUND_UP;若为负,则舍入行为同ROUND_DOWN(此舍入模式始终不会减少计算值大小)
0.833333… → 0.83334
-0.833333… → -0.83333
- BigDecimal.Round_FLOOR 接近负无穷大(不是无穷小)的舍入模式。其行为与ROUND_CEILING相反,若BigDecimal为负,则舍入行为同ROUND_UP;若为正,则舍入行为同ROUND_DOWN(此舍入模式始终不会增加计算值大小)
0.833333… → 0.83333
-0.833333… → -0.83334
- BigDecimal.Round_HALF_UP 向最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式(四舍五入,即舍弃部分>=0.5则向上舍入,否则向下舍入)
0.9166666… → 0.91667
0.833333… → 0.83333
- BigDecimal.Round_HALF_DOWN 向最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式(舍弃部分<=0.5则向下舍入,否则向上舍入) 0.9166666… → 0.91667
0.833333… → 0.83333
- BigDecimal.Round_HALF_EVEN 向最接近的数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入(在重复进行一系列计算时,此舍入模式可以将累加错误减到最小)
3.3333333… → 3.33333
0.9166666… → 0.91667
- BigDecimal.Round_UNNECESSARY 断言请求的操作具有精确的结枚,因此不需要舍入,若该操作无精确结果(如1/3)则抛出 ArithmeticException
1 → 1.00000
0.333333… → ArithmeticException
六、其他
1.比较大小可以用 $a.compareTo(b) $
返回值
-1: 小于
0 :等于
1 :大于
2. B i g D e c i m a l BigDecimal BigDecimal 取其中最大、最小值、绝对值、相反数:
a.max (b) //比较取最大值
a.min(b) //比较取最小值
a.abs()//取最绝对值
a.negate()//取相反数
七、应用举例
2019年CCPC网络赛某题目,判断两个数相除是否为会产生无限小数。
这时我们应用 B i g D e c i m a l BigDecimal BigDecimal 的 d i v i d e divide divide 方法,如果出现无限小数会抛出异常,这时我们可以接受异常再判断,是不是很简单
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
String s1, s2;
Scanner scanner = new Scanner(System.in);
s1 = scanner.next();
s2 = scanner.next();
BigDecimal b1 = new BigDecimal(s1);
BigDecimal b2 = new BigDecimal(s2);
try {
b1 = b1.divide(b2);
System.out.println("No");
} catch (Exception e) {
System.out.println("Yes");
}
}
}