欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java 类BigDecimal:金额相关以及compareto比较

程序员文章站 2022-07-10 18:47:58
java知识点:BigDecimal:金额相关以及compareto比较,集合排序...

BigDecimal:金额相关

BigDecimal 是java小数操作的一个专有类,在电商、金融行业 存储跟金额有关的字段

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算,双精度浮点型变量double可以处理16位有效数。不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度,在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象

     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.lang.ArithmeticException

     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 BigDecimal(Double.toString(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, c.compareTo(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 = NumberFormat.getCurrencyInstance();    //建立货币格式化引用
NumberFormat percent = NumberFormat.getPercentInstance();     //建立百分比格式化用
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());

附 java中的compareto方法

返回为正数表示a1>a2, 返回为负数表示a1<a2, 返回为0表示a1==a2;

除了基本类型(< = >);Date、String、Integer、或者其他的,可以直接使用compareTo比较

  • 返回参与比较的前后两个字符串的asc码的差值,如果两个字符串首字母不同,则该方法返回首字母的asc码的差值


String a1 = "a";
String a2 = "c";
System.out.println(a1.compareTo(a2));//结果为-2
  • 参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值


String a1 = "aa";
String a2 = "ad";
System.out.println(a1.compareTo(a2));//结果为-3
  • 如果两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值


String a1 = "aa";
String a2 = "aa12345678";
System.out.println(a1.compareTo(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.bookName.compareTo(o.bookName);//按书名排序 升序
    //先按 id 再按价格 最后按书名排序 升序
    int result = this.bookId - o.bookId;
    if(result == 0){
        result =this.bookPrice - o.bookPrice;
    }
    if(result == 0){
        result = this.bookName.compareTo(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
                
                return o1.getBookPrice() - o2.getBookPrice();
                
            }
        });

// JDK1.8
Collections.sort(books,(Book a, Book b) -> { return a.getBookPrice()-b.getBookPrice(); });

// 简写1
Collections.sort(books,(Book a, Book b) ->  a.getBookPrice()-b.getBookPrice());
// 简写2
Collections.sort(list, Comparator.comparingInt(Channel::getChnumber));

treeMap 中(基于key的排序)

treeMap默认的是基于key的从小到大 的排列
自定义排序也是基于key的,如果key object类型 可以自定义各种排序

TreeMap<String, Person> treeMap = new TreeMap<>((String a,String b)-> b.compareTo(a));//降序
TreeMap<String, Person> treeMap = new TreeMap<>((String a,String b)-> a.compareTo(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<>(treeMap.entrySet());

Collections.sort(entries,
        (Map.Entry<String, User> e1, Map.Entry<String, User> e2) -> ((User) e1.getValue()).getUserName()
                .compareTo(((User) e2.getValue()).getUserName()));
System.out.println("按名字顺序排列");
for (Entry<String, User> entry : entries) {
    System.out.println(entry.getValue());

}

更多java常用知识点整理:https://blog.csdn.net/qq_44695727/article/details/101054712