java知识点:BigDecimal:⾦额相关的计算、打印以及
compareto⽐较和Bi。。。
⽬录
BigDecimal:⾦额相关
BigDecimal 是java⼩数操作的⼀个专有类,在电商、⾦融⾏业 存储跟⾦额有关的字段
Java在java.math包中提供的API类BigDecimal,⽤来对超过16位有效位的数进⾏精确的运算,双精度浮点型变量double可以处理16位有效数。不论是float 还是double
BigDecimal a = new BigDecimal(5);
BigDecimal b = new BigDecimal(40);
BigDecimal add = a.add(b); // +
BigDecimal subtract = a.subtract(b); // -
BigDecimal multiply = a.multiply(b); // *
BigDecimal divide = a.divide(b); // \
BigDecimal result5 = num2.divide(num1, 20, BigDecimal.ROUND_HALF_UP)//(已过时)后⾯说明,第⼆个参数为保留⼏位⼩数, 务必写成这种,防⽌异常java BigDecimal result4 = num3.abs(); //绝对值
注意: System.out.println()中的数字默认是double类型的,double类型⼩数计算不精准。
使⽤BigDecimal类构造⽅法传⼊double类型时,计算的结果也是不精确的!
取整:
BigDecimal bd = new BigDecimal("12.1");
long l = bd.setScale( 0, BigDecimal.ROUND_UP ).longValue(); // 向上取整
long l = bd.setScale( 0, BigDecimal.ROUND_DOWN ).longValue(); // 向下取整
BigDecimal b = new BigDecimal("2.225667").setScale(2, BigDecimal.ROUND_DOWN);
//b = 2.22 直接去掉多余的位数
BigDecimal c = new BigDecimal("2.224667").setScale(2, BigDecimal.ROUND_UP);
//c = 2.23 跟上⾯相反,进位处理
因为不是所有的浮点数都能够被精确的表⽰成⼀个double 类型值,有些浮点数值不能够被精确的表⽰成 double 类型值,因此它会被表⽰成与它最接近的 double 类型的值。必须改⽤传⼊String的构造⽅法。这⼀点在BigDecimal类的构造⽅法注释中有说明
//尽量⽤字符串的形式初始化
BigDecimal num12 = new BigDecimal("0.005");
BigDecimal num12 = new String(d));
BigDecimal num12 = BigDecimal.valueOf(1.010);
// 使⽤string类型额构造函数进⾏构造时,equals⽆法⽐较,⽐如多余的0
// compareTo⽅法则只会进⾏⼤⼩的⽐较,与精度⽆关:1.010=1.01为true
compareTo返回为正数表⽰a1>a2, 返回为负数表⽰a1<a2, 返回为0表⽰a1==a2;
// c=1.010 ,b=1.01, cpareTo(b) = 0 //b c 都是BigDecimal类型
// 使⽤valueof⽅法进⾏构造时,他会帮我们去掉多余的精度可以⽤equals⽐较
// c.equals(b) = true
BigDecimal 精度描述:
模式 描述
CEILING 正⽆穷⼤⽅向取整
FLOOR 负⽆穷⼤⽅向取整
DOWN 向 0 的⽅向取整
UP 正数向正⽆穷⼤取整,负数向负⽆穷⼤取整
HALF_UP 5,6,7,8,9 向上取整、 1,2,3,4 向下取整、 常⽤的4舍5⼊
HALF_DOWN 6,7,8,9 向上取整 1,2,3,4,5 向下取整
HALF_EVEN ⼩数位是5时,判断整数部分是奇数就进位、 ⼩数位是5时,判断整数部分是偶数就舍弃、
1,2,3,4, 舍弃、 6,7,8,9, 进位
常⽤⽅法PS
currency = CurrencyInstance(); //建⽴货币格式化引⽤
NumberFormat percent = PercentInstance(); //建⽴百分⽐格式化⽤
percent.setMaximumFractionDigits(3); //百分⽐⼩数点最多3位
currency.format(bigLoanAmount)
percent.format(bigInterestRate)
currency.format(bigInterest)
BigDecimal数字数据转String⽂本,避免输出科学计数法
直接返回给前端的话11.00会显⽰为11,
// 浮点数的打印
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").toPlainString());
// 四舍五⼊,保留两位⼩数,避免输出科学计数法
System.out.println(new BigDecimal("100.000").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); // ⽅法已过时,说明更新在下⽅System.out.println(new BigDecimal("100.000").setScale(2));
System.out.println(new BigDecimal("100.000").setScale(2, RoundingMode.HALF_UP));
java.math.RoundingMode ⼏个参数详解
RoundingMode.CEILING:取右边最近的整数
RoundingMode.DOWN:去掉⼩数部分取整,也就是正数取左边,负数取右边,相当于向原点靠近的⽅向取整
RoundingMode.FLOOR:取左边最近的正数
RoundingMode.HALF_DOWN:五舍六⼊,负数先取绝对值再五舍六⼊再负数
RoundingMode.HALF_UP:四舍五⼊,负数原理同上
RoundingMode.HALF_EVEN:这个⽐较绕,整数位若是奇数则四舍五⼊,若是偶数则五舍六⼊
附 java中的compareto⽅法
返回为正数表⽰a1>a2, 返回为负数表⽰a1<a2, 返回为0表⽰a1==a2;
除了基本类型(< = >);Date、String、Integer、或者其他的,可以直接使⽤compareTo⽐较
返回参与⽐较的前后两个字符串的asc码的差值,如果两个字符串⾸字母不同,则该⽅法返回⾸字母的asc码的差值
String a1 = "a";
String a2 = "c";
System.out.println(a1pareTo(a2));//结果为-2
参与⽐较的两个字符串如果⾸字符相同,则⽐较下⼀个字符,直到有不同的为⽌,返回该不同的字符的asc码差值
String a1 = "aa";
String a2 = "ad";
System.out.println(a1pareTo(a2));//结果为-3
如果两个字符串不⼀样长,可以参与⽐较的字符⼜完全⼀样,则返回两个字符串的长度差值
String a1 = "aa";
String a2 = "aa12345678";
System.out.println(a1pareTo(a2));//结果为-8
compareToIgnoreCase忽略⼤⼩写
Comparable<T>接⼝中的compareTo
compareTo⽅法内必须做⾮空判断(规范问题),当然int类型就不⽤了。
1、模型必须实现Comparable<T>接⼝
2、Collection.sort(list)会⾃动调⽤compareTo,如果没有这句,list是不会排序的,也不会调⽤compareTo⽅法
3、如果是数组则⽤Arrays.sort(a)⽅法
// 实体类重写
@Override
public int compareTo(Book o) {
// TODO Auto-generated method stub
//return this.bookPrice-o.bookPrice;//按价格排序升序
//return o.bookPrice-this.bookPrice;//按价格排序降序
//return this.bookNamepareTo(o.bookName);//按书名排序升序
//先按 id 再按价格最后按书名排序升序
int result = this.bookId - o.bookId;
if(result == 0){
result =this.bookPrice - o.bookPrice;
}
if(result == 0){
result = this.bookNamepareTo(o.bookName);
}
return result;
}
// 使⽤
Collections.sort(books);
list排序
// JDK1.8以前的⽼⽤法,之前⼀直这样写
Collections.sort(books,new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
// TODO Auto-generated method stub
BookPrice() - o2.getBookPrice();
}
});
// JDK1.8
Collections.sort(books,(Book a, Book b) -> { BookPrice()-b.getBookPrice(); });
// 简写1
Collections.sort(books,(Book a, Book b) -> a.getBookPrice()-b.getBookPrice());
// 简写2
Collections.sort(list, ComparatorparingInt(Channel::getChnumber));
treeMap 中(基于key的排序)
treeMap默认的是基于key的从⼩到⼤的排列
⾃定义排序也是基于key的,如果key object类型可以⾃定义各种排序
TreeMap<String, Person> treeMap = new TreeMap<>((String a,String b)-> bpareTo(a));//降序
bigdecimal格式化两位小数TreeMap<String, Person> treeMap = new TreeMap<>((String a,String b)-> apareTo(b));//升序
TreeMap的按value排序
(转换成entry list 然后排序)汉字是按ascii码排序的,不是汉语拼⾳
User p1 = new User(1, "A⼩红");
User p2 = new User(5, "D赵明");
User p3 = new User(2, "W孙宇");
User p4 = new User(9, "C黎明");
TreeMap<String, User> treeMap = new TreeMap<>();
treeMap.put("45", p1);
treeMap.put("12", p2);
treeMap.put("85", p3);
treeMap.put("33", p4);
List<Map.Entry<String, User>> entries = new ArrayList<>(Set());
Collections.sort(entries,
(Map.Entry<String, User> e1, Map.Entry<String, User> e2) -> ((User) e1.getValue()).getUserName()
pareTo(((User) e2.getValue()).getUserName()));
System.out.println("按名字顺序排列");
for (Entry<String, User> entry : entries) {
System.out.Value());
}
过时⽅法说明:BigDecimal.ROUND_HALF_UP
BigDecimal.ROUND_HALF_UP
BigDecimal中的过时⽅法:
ROUND_UP:舍⼊远离零的舍⼊模式,在丢弃⾮零部分之前始终增加数字(始终对⾮零舍弃部分前⾯的数字加1)。此舍⼊模式始终不会减少计算值的⼤⼩。ROUND_DOWN:接近零的舍⼊模式,在丢弃某部分之前始终不增加数字(从不对舍弃部分前⾯的数字加1,即截短)。此舍⼊模式始终不会增加计算值的⼤⼩。ROUND_CEILING:接近正⽆穷⼤的舍⼊模式。如果 BigDecimal 为正,则舍⼊⾏为与 ROUND_UP 相同;如果为负,则舍⼊⾏为与 ROUND_DOWN 相同。此舍⼊ROUND_FLOOR:接近负⽆穷⼤的舍⼊模式。如果 BigDecimal 为正,则舍⼊⾏为与 ROUND_DOWN 相同;如果为负,则舍⼊⾏为与 ROUND_UP 相同。此舍⼊模
ROUND_FLOOR:接近负⽆穷⼤的舍⼊模式。如果 BigDecimal 为正,则舍⼊⾏为与 ROUND_DOWN 相同;如果为负,则舍⼊⾏为与 ROUND_UP 相同。此舍⼊模ROUND_HALF_UP:向“最接近的”数字舍⼊,如果与两个相邻数字的距离相等,则为向上舍⼊的舍⼊模式。如果舍弃部分 >= 0.5,则舍⼊⾏为与 ROUND_UP 相同ROUND_HALF_DOWN:向“最接近的”数字舍⼊,如果与两个相邻数字的距离相等,则为上舍⼊的舍⼊模式。如果舍弃部分 > 0.5,则舍⼊⾏为与 ROUND_UP 相ROUND_HALF_EVEN 银⾏家舍⼊法:向“最接近的”数字舍⼊,如果与两个相邻数字的距离相等,则向相邻的偶数舍⼊。如果舍弃部分左边的数字为奇数,则舍⼊1.15>1.2 1.25>1.2
ROUND_UNNECESSARY:断⾔请求的操作具有精确的结果,因此不需要舍⼊。如果对获得精确结果的操作指定此舍⼊模式,则抛出ArithmeticException。
替换⽅案:java.math.RoundingMode
java.math.RoundingMode ⼏个参数详解
RoundingMode.CEILING:取右边最近的整数
RoundingMode.DOWN:去掉⼩数部分取整,也就是正数取左边,负数取右边,相当于向原点靠近的⽅向取整
RoundingMode.FLOOR:取左边最近的正数
RoundingMode.HALF_DOWN:五舍六⼊,负数先取绝对值再五舍六⼊再负数
RoundingMode.HALF_UP:四舍五⼊,负数原理同上
RoundingMode.HALF_EVEN:这个⽐较绕,整数位若是奇数则四舍五⼊,若是偶数则五舍六⼊
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论