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为truecompareTo返回为正数表示a1>a2, 返回为负数表示a1
// c=1.010 ,b=1.01, c.compareTo(b) = 0 //b c 都是BigDecimal类型
// 使用valueof方法进行构造时,他会帮我们去掉多余的精度可以用equals比较
// c.equals(b) = trueBigDecimal 精度描述:
模式 描述
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
除了基本类型(< = >);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
接口中的compareTo compareTo方法内必须做非空判断(规范问题),当然int类型就不用了。 1、模型必须实现Comparable
接口 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
() { @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
treeMap = new TreeMap<>((String a,String b)-> b.compareTo(a));//降序 TreeMap 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
treeMap = new TreeMap<>(); treeMap.put("45", p1); treeMap.put("12", p2); treeMap.put("85", p3); treeMap.put("33", p4); List > entries = new ArrayList<>(treeMap.entrySet()); Collections.sort(entries, (Map.Entry e1, Map.Entry e2) -> ((User) e1.getValue()).getUserName() .compareTo(((User) e2.getValue()).getUserName())); System.out.println("按名字顺序排列"); for (Entry entry : entries) { System.out.println(entry.getValue()); } 更多java常用知识点整理:https://blog.csdn.net/qq_44695727/article/details/101054712