概述
标题
- Java BigDecimal 的舍入模式 (RoundingMode)详解
- 提一下银行家算法
- BigDecimal和BigInteger
- Java中BigDecimal常用方法
- BigDecimal的toString()方法和toPlainString()方法
- BigDecimal 返回前端保留小数点后两位问题解决
BigDecimal是不可变、任意精度的有符号 十进制数。
一般是用在大金额结算等对数值精度要求较高的领域(因为浮点数如float、double表示小数的精确度不足,仅可以处理16位有效数字),但其运算性能低于Double、Float等,在一般的工程领域数值计算也不会随便用BigDecimal。
Java BigDecimal 的舍入模式 (RoundingMode)详解
值得注意的是,除法一般都是需要确定保留多少位小数的BigDecimal
bigDecimal = a.divide(b,2,RoundingMode.HALF_UP);,如果不设置保留的小数位Scale,就可能会抛出ArithmeticException异常。这是因为a.divide(b)会默认使用ROUND_UNNECESSARY模式,即不做舍入处理,如果计算结果的小数位和要求保留的小数位不相符,则抛出异常。
下面假设如保留两位小数:(保留两位小数只关心第三位小数),根据第三位小数为0 及<5、=5、>5的情况分析得出如下结论:
注意如果不足两位小数则填充0保证两位小数 还需要注意new BigDecimal("-0")(无论-0还是0)保留两位小数都是0.00
至于负数情况只是前面加个负号。
舍入策略 | 注意点 | 代码标志 | 对应源码值 | 核心功能特点 |
---|---|---|---|---|
第三位小数只要>0 就进1 | (0 除外)都会进1,负数加- 即可 | ROUND_UP | 0 | 向上取整 |
第三位小数直接舍去 | 直接舍去,负数加- 即可 | ROUND_DOWN | 1 | 向下取整 |
第三位小数>=5 ,进行四舍五入 | 负数加- 即可 | ROUND_HALF_UP | 4 | 常规四舍五入 |
第三位小数>5 ,进行五舍六入 | 负数加- 即可 | ROUND_HALF_DOWN | 5 | 常规五舍六入 |
如果为正数等价于:ROUND_UP;为负数等价于:ROUND_DOWN | ROUND_UP、ROUND_DOWN 的搭配正用 | ROUND_CEILING | 2 | 此模式会增加数值大小 |
如果为正数等价于:ROUND_DOWN;为负数等价于:ROUND_UP | ROUND_UP、ROUND_DOWN 的搭配逆用 | ROUND_FLOOR | 3 | 此模式不会增加数值大小 |
四舍六入五成双 | 四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一 | ROUND_HALF_EVEN | 6 | 银行家算法 |
断言我对目标数保留的位数是否>=目标数的位数 | 无舍入逻辑即不需要舍入,不满足则会报错:ArithmeticException | ROUND_UNNECESSARY | 7 | 具备断言(判断)功能 |
看以上表格我说一嘴:
- RoundingMode取值范围
0到7
否则报错:java.lang.IllegalArgumentException: Invalid rounding mode - ROUND_HALF_EVEN 一般是业务中最常用的,也是这几种保留策略最复杂的,看完案例其实还是很简单的,技巧是 四舍六入五考虑,五后非零就进一(原数位数比你要保留的位数多至少2位),五后为零看奇偶,五前为偶应舍去,五前为奇要进一
- 对表格里面说法不理解请看下面具体每个的案例。
可参考此内容
ROUND_UP
进位制:不管保留数字后面是大是小 (0 除外) 都会进 1。结果会向原点的反方向对齐,
正数向正无穷方向对齐,负数向负无穷方向对齐。
BigDecimal a = new BigDecimal("0.090").setScale(2, 0); // 0.09
BigDecimal a1 = new BigDecimal("0.091").setScale(2, BigDecimal.ROUND_UP); // 0.10
BigDecimal a2 = new BigDecimal("-0.090").setScale(2, BigDecimal.ROUND_UP); // -0.09
BigDecimal a3 = new BigDecimal("-0.091").setScale(2, BigDecimal.ROUND_UP); // -0.10
BigDecimal a4 = new BigDecimal("-0.1").setScale(2, BigDecimal.ROUND_UP); // -0.10
BigDecimal a5 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_UP); // 0.00
ROUND_DOWN
舍去制,截断操作,后面所有数字直接去除。结果会向原点方向对齐。
BigDecimal a = new BigDecimal("0.090").setScale(2, 1); // 0.09
BigDecimal a1 = new BigDecimal("0.091").setScale(2, BigDecimal.ROUND_DOWN); // 0.09
BigDecimal a2 = new BigDecimal("-0.090").setScale(2, BigDecimal.ROUND_DOWN); // -0.09
BigDecimal a3 = new BigDecimal("-0.091").setScale(2, BigDecimal.ROUND_DOWN); // -0.09
BigDecimal a4 = new BigDecimal("-0.1").setScale(2, BigDecimal.ROUND_DOWN); // -0.10
BigDecimal a5 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_DOWN); // 0.00
ROUND_HALF_UP
根据保留数字后一位 >=5 进行四舍五入。如果舍弃部分的最高位大于等于 5,向原点反方向对齐,否则向原点方向对齐。
BigDecimal a = new BigDecimal("0.090").setScale(2, 4); // 0.09
BigDecimal a1 = new BigDecimal("0.091").setScale(2, BigDecimal.ROUND_HALF_UP); // 0.09
BigDecimal a2 = new BigDecimal("-0.091").setScale(2, BigDecimal.ROUND_HALF_UP); // -0.09
BigDecimal a3 = new BigDecimal("0.095").setScale(2, BigDecimal.ROUND_HALF_UP); // 0.10
BigDecimal a4 = new BigDecimal("-0.095").setScale(2, BigDecimal.ROUND_HALF_UP); // -0.10
BigDecimal a5 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_HALF_UP); // 0.00
ROUND_HALF_DOWN
根据保留数字后一位 >5 进行五舍六入。如果舍弃部分的最高位大于 5,向原点反方向对齐,否则向原点方向对齐。 这种模式也就是我们常说的 “五舍六入”。
BigDecimal a = new BigDecimal("0.095").setScale(2, 5); // 0.09
BigDecimal a1 = new BigDecimal("0.095").setScale(2, BigDecimal.ROUND_HALF_DOWN); // 0.09
BigDecimal a2 = new BigDecimal("-0.095").setScale(2, BigDecimal.ROUND_HALF_DOWN); // -0.09
BigDecimal a3 = new BigDecimal("0.096").setScale(2, BigDecimal.ROUND_HALF_DOWN); // 0.10
BigDecimal a4 = new BigDecimal("-0.096").setScale(2, BigDecimal.ROUND_HALF_DOWN); // -0.10
BigDecimal a5 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_HALF_DOWN); // 0.00
ROUND_CEILING
向正无穷方向对齐,转换为正无穷方向最接近的数值。如果为正数,行为和 ROUND_UP 一样;
如果为负数,行为和 ROUND_DOWN 一样。此模式不会减少数值大小。
BigDecimal a = new BigDecimal("0.095").setScale(2, 2); // 0.10
BigDecimal a1 = new BigDecimal("0.095").setScale(2, BigDecimal.ROUND_CEILING); // 0.10
BigDecimal a2 = new BigDecimal("-0.095").setScale(2, BigDecimal.ROUND_CEILING); // -0.09
BigDecimal a3 = new BigDecimal("0.096").setScale(2, BigDecimal.ROUND_CEILING); // 0.10
BigDecimal a4 = new BigDecimal("-0.096").setScale(2, BigDecimal.ROUND_CEILING); // -0.09
BigDecimal a5 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_CEILING); // 0.00
ROUND_FLOOR
向负无穷方向对齐。如果为正数,行为和 ROUND_DOWN 一样;
如果为负数,行为和 ROUND_UP 一样。此模式不会增加数值大小。
BigDecimal a = new BigDecimal("0.095").setScale(2, 3); // 0.09
BigDecimal a1 = new BigDecimal("0.095").setScale(2, BigDecimal.ROUND_FLOOR); // 0.09
BigDecimal a2 = new BigDecimal("-0.095").setScale(2, BigDecimal.ROUND_FLOOR); // -0.10
BigDecimal a3 = new BigDecimal("0.096").setScale(2, BigDecimal.ROUND_FLOOR); // 0.09
BigDecimal a4 = new BigDecimal("-0.096").setScale(2, BigDecimal.ROUND_FLOOR); // -0.10
BigDecimal a5 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_FLOOR); // 0.00
ROUND_HALF_EVEN
技巧:>6或=5且前一位为奇数进1,4>或=5且前一位为偶数舍去
四舍六入五成双,如果舍弃部分的最高位大于等于六,或等于五并且前一位是奇数,向原点反方向对齐,否则向原点方向对齐。
如果舍弃部分左边的数字为奇数,则作 ROUND_HALF_UP;如果为偶数,则作ROUND_HALF_DOWN。
ROUND_HALF_UP 根据保留数字后一位 >=5 进行四舍五入。
ROUND_HALF_DOWN 根据保留数字后一位 >5 进行五舍六入。
四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。
BigDecimal a = new BigDecimal("0.035").setScale(2, 6); // 0.04
BigDecimal a1 = new BigDecimal("0.045").setScale(2, BigDecimal.ROUND_HALF_EVEN); // 0.04
BigDecimal a2 = new BigDecimal("0.055").setScale(2, BigDecimal.ROUND_HALF_EVEN); // 0.06
BigDecimal a3 = new BigDecimal("0.065").setScale(2, BigDecimal.ROUND_HALF_EVEN); // 0.06
BigDecimal a4 = new BigDecimal("0.075").setScale(2, BigDecimal.ROUND_HALF_EVEN); // 0.08
BigDecimal a5 = new BigDecimal("-0.035").setScale(2, 6); // -0.04
BigDecimal a6 = new BigDecimal("-0.045").setScale(2, BigDecimal.ROUND_HALF_EVEN); // -0.04
BigDecimal a7 = new BigDecimal("-0.055").setScale(2, BigDecimal.ROUND_HALF_EVEN); // -0.06
BigDecimal a8 = new BigDecimal("-0.065").setScale(2, BigDecimal.ROUND_HALF_EVEN); // -0.06
BigDecimal a9 = new BigDecimal("-0.075").setScale(2, BigDecimal.ROUND_HALF_EVEN); // -0.08
BigDecimal a10 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_HALF_EVEN); // 0.00
BigDecimal a11 = new BigDecimal("-0.0851").setScale(2, BigDecimal.ROUND_HALF_EVEN); // -0.09
ROUND_UNNECESSARY
注意点
1、无舍入逻辑即不需要舍入,
2、也就是作用 断言我对目标数保留的位数是否>=目标数的位数
断言请求的操作具有精确的结果,因此不需要舍入。
如果对获得非精确结果的操作指定此舍入模式,则抛出 ArithmeticException。
//Exception in thread "main" java.lang.ArithmeticException: Rounding necessary
//BigDecimal a = new BigDecimal("0.035").setScale(2, BigDecimal.ROUND_UNNECESSARY);
BigDecimal a1 = new BigDecimal("0.03").setScale(2, BigDecimal.ROUND_UNNECESSARY);//0.03
BigDecimal a2 = new BigDecimal("0.3").setScale(2, BigDecimal.ROUND_UNNECESSARY);//0.30
BigDecimal a3 = new BigDecimal("300").setScale(2, BigDecimal.ROUND_UNNECESSARY);//300.00
BigDecimal a5 = new BigDecimal("-0.03").setScale(2, BigDecimal.ROUND_UNNECESSARY);//-0.03
BigDecimal a6 = new BigDecimal("-0").setScale(2, BigDecimal.ROUND_UNNECESSARY); // 0.00
==RoundingMode取值范围0到7 ==
否则,java.lang.IllegalArgumentException: Invalid rounding mode
//BigDecimal a9 = new BigDecimal("-0").setScale(2, 8);//IllegalArgumentException
提一下银行家算法
BigDecimal和BigInteger
一个针对浮点一个针对整形操作。
当对数字精度要求比较高时使用,BigInteger是对比Long范围还大的数字操作,而BigDecimal是比double还要精确的数字操作
主要有加减乘除方法:add()相加, subtract()相减, multiply()相乘, divide()相除。
顺便说一下,java.util包中的Scanner类实现了nextBigInteger()和nextBigDecimal()方法,可以用来读入控制台输入的BigInteger和BigDecimal。
BigInteger i1 = new BigInteger("79846513898465139846513289653");
BigInteger i2 = new BigInteger("46513986539856298465398465132");
//add()相加, subtract()相减, multiply()相乘, divide()相除
BigInteger i3 = i1.add(i2);
System.out.println( i3 );
System.out.println( i1.subtract(i2));
System.out.println( i1.multiply(i2));
System.out.println( i1.divide(i2));
//小数有可能会出现除不断的情况
BigDecimal d1 = new BigDecimal("79846597846513984653978465.985");
BigDecimal d2 = new BigDecimal("465132645132978465.985");
//小数相除,如果除不断就会产生java.lang.ArithmeticException算术异常
//小数相除时,经常指定小数的位数(这里保留10位小数), 及尾数的处理方式
System.out.println( d1.divide(d2, 10, RoundingMode.FLOOR));
//RoundingMode是一种枚举类型, 枚举可以看作是一组常量的组合
//枚举也是一种引用数据类型, 可以定义变量, 赋值时只能赋值枚举类型中定义的常量值
RoundingMode mode = RoundingMode. ROUND_HALF_UP;// 表示的就是4舍5入
下面说点不重要的东西,多知道一点
numBits范围非负数即>=0
System.out.println("构造两个BigInteger对象");
BigInteger bi1 = new BigInteger(55,new Random());
BigInteger bi2 = new BigInteger(new byte[]{3,2,3});
System.out.println("bi1 + bi2 = " + bi1.add(bi2)); //加
System.out.println("bi1 - bi2 = " + bi1.subtract(bi2)); //减
System.out.println("bi1 * bi2 = " + bi1.multiply(bi2)); //乘
System.out.println("bi1的2次方 = " + bi1.pow(2)); //指数运算
//因为是整形我就不存在小数,小数根据舍入规则舍弃了
System.out.println("bi1/bi2的整数商: " + bi1.divide(bi2)); //整数商
System.out.println("bi1/bi2的余数: " + bi1.remainder(bi2));//余数
//todo 整数商+余数
System.out.println("bi1 / bi2 = " + bi1.divideAndRemainder(bi2)[0] +
"--" + bi1.divideAndRemainder(bi2)[1]);
System.out.println("bi1 + bi2 = " + bi1.add(bi2));
//比较大小,也可以用max()和min()
if(bi1.compareTo(bi2) > 0){
System.out.println("bi1 is greater than bi2");
}
else if(bi1.compareTo(bi2) == 0){
System.out.println("bi1 is equal to bi2");
}else if(bi1.compareTo(bi2) < 0){
System.out.println("bd1 is lower than bd2");
}
BigInteger bi3 = bi1.negate();
System.out.println("bi1的相反数:" + bi3); //返回相反数
System.out.println("bi1的绝对值:" + bi3.abs());//返回绝对值
转换进制
String string1 = new BigInteger("20", 10).toString(2);
System.out.println("TAG 十进制的20转换成二进制是:" + string1);
String string2 = new BigInteger("20", 10).toString(8);
System.out.println("TAG 十进制的20转换成八进制是:" + string2);
String string3 = new BigInteger("20", 10).toString(16);
System.out.println("TAG 十进制的20转换成十六进制是:" + string3);
String string4 = new BigInteger("110", 2).toString(10);
System.out.println("TAG 二进制的110转换成十进制是:" + string4);
String string5 = new BigInteger("110", 8).toString(10);
System.out.println("TAG 八进制的110转换成十进制是:" + string5);
String string6 = new BigInteger("110", 16).toString(10);
System.out.println("TAG 十六进制的110转换成十进制是:" + string6);
Java中BigDecimal常用方法
来点不一样的玩法
System.out.println("构造两个BigDecimal对象");
//用char[]数组创建BigDecimal对象,第二个参数为位移offset, 第三个参数指定长度
BigDecimal bd1 = new BigDecimal("3464656776868432998434".toCharArray(), 2, 15);
//用double类型创建BigDecimal对象 下面肯定会精度丢失
BigDecimal bd2 = new BigDecimal(134258767575867.0F);
System.out.println("bd1 + bd2 = " + bd1.add(bd2)); //加
System.out.println("bd1 - bd2 = " + bd1.subtract(bd2));//减
System.out.println("bd1 * bd2 = " + bd1.multiply(bd2));//乘
System.out.println("bd1的2次方 = " + bd1.pow(2));//指数运算
//todo 取商的整数部分
System.out.println("bd1/bd2的整数商: " + bd1.divideToIntegralValue(bd2));
// 返回余数计算为:this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))
System.out.println("bd1/bd2的余数: " + bd1.subtract(bd1.divideToIntegralValue(bd2).multiply(bd2)));
System.out.println("bd1/bd2的余数: " + bd1.remainder(bd2));
//取商和余,即bd1.divideToIntegralValue(bd2)与bd1.remainder(bd2)
System.out.println("bd1 / bd2 = " + bd1.divideAndRemainder(bd2)[0] +
"--" + bd1.divideAndRemainder(bd2)[1]);
//比较大小,也可以用max()和min()
if (bd1.compareTo(bd2) > 0) {
System.out.println("bd1 is greater than bd2");
} else if (bd1.compareTo(bd2) == 0) {
System.out.println("bd1 is equal to bd2");
} else if (bd1.compareTo(bd2) < 0) {
System.out.println("bd1 is lower than bd2");
}
//末位数据精度 整数为1 小数为其小数点精度
//返回该BigDecimal的最后一个单位ulp的大小。非零BigDecimal值的ulp是该值与具有相同位数的下一个较大的BigDecimal值之间的正距离。
// ulp为0时,在这个比例下数值等于1。结果以相同的比例存储,因此0和非0值的结果等于[1,this.scale()]。
System.out.println("bd1的末位数据精度: " + bd1.ulp());
System.out.println("末位数据精度: " + new BigDecimal("123.21").ulp());//0.01
System.out.println("末位数据精度: " + new BigDecimal("123.21134").ulp());//0.00001
System.out.println("末位数据精度: " + new BigDecimal("123").ulp());//1
System.out.println("末位数据精度: " + new BigDecimal("0").ulp());//1
为什么说总是使用compareTo()比较两个BigDecimal的值,不要使用equals()!
BigDecimal d1 = new BigDecimal(“123.456”);
操作数据工具类,
比如±*/的基本操作,还有,相反数,最大公约数,是否是质数等等的运算。
BigDecimal转BigInteger
获取小数位数、小数精度,绝对值、不绝对值、取反、去除小数点后无用0、
取商的整数部分、取余数、返回商跟余数、
返回一个BigDecimal,设置指定保留位数,及舍入策略。
返回BigDecimal和val的最大值、最小值。
向左向右移动小数点的方法、判断一个数是正数、0、还是负数
/**
* 获取小数位数
*/
public static int getScale(BigDecimal b) {
return b.scale();
}
//上面的升级版,去掉后面的0
public static int getScale2(BigDecimal b) {
return b.stripTrailingZeros().scale();
}
/**
* 获取小数精度 大于6位小数后采用科学计数法
* 末位数据精度 整数为1 小数为其小数点精度
*/
public static BigDecimal getUlpDecimal(BigDecimal b) {
return b.ulp();
}
//去除末尾无用的0后的小数精度
public static BigDecimal getUlpDecimal2(BigDecimal b) {
return b.stripTrailingZeros().ulp();
}
/**
* 方法返回此BigDecimal的精度。精度是指非标度值中的位数。
* 这个不会科学计数,但是返回值跟上面不一样,
* 此方法返回一个整数,该整数表示此BigDecimal对象的精度。
* Input : 198.176 Output : 6
* Input : 721111.111 Output : 9
* Input : 0.3 Output : 1
*
*/
public static int precisionBigDecimal(BigDecimal bd){
return bd.precision();
}
public static int precisionBigDecimal2(BigDecimal bd){
return bd.stripTrailingZeros().precision();
}
/**
* 获取绝对值---负数转正数
*/
public static BigDecimal getABSBigDecimal(BigDecimal b) {
return b.abs();
}
/**
* 跟绝对值反着来---正数转负数
*/
public static BigDecimal getNotABSBigDecimal(BigDecimal b) {
BigDecimal abs = b.abs();
return new BigDecimal("-" + b.abs());
}
/**
* 返回相反数---正数转负数,负数转正数(作用就是负数去负号,正数加负号)
* 如果你需要进行取舍的话他还支持 传参MathContext. 具体规则自行百度
*/
public static BigDecimal getNegateBigDecimal(BigDecimal b) {
return b.negate();
}
/**
* 取商的整数部分(直接把小数舍去)
* bd1/bd2的整数商
*/
public static BigDecimal getDivShang(BigDecimal bd1, BigDecimal bd2) {
return bd1.divideToIntegralValue(bd2);
}
/**
* 返回余数计算 (直接把小数舍去)
* bd1/bd2的整数商
*/
public static BigDecimal getDivMod(BigDecimal bd1, BigDecimal bd2) {
return bd1.remainder(bd2);
// return bd1.subtract(bd1.divideToIntegralValue(bd2).multiply(bd2));
}
/**
* 取商和余,即bd1.divideToIntegralValue(bd2)与bd1.remainder(bd2)
*/
public static String getDivShangAndMod(BigDecimal bd1, BigDecimal bd2) {
return bd1.divideAndRemainder(bd2)[0] + "余" + bd1.divideAndRemainder(bd2)[1];
}
/**
* 返回一个BigDecimal,它在数值上与此值相等,但从表示形式中移除尾随的任何零。
*/
public static BigDecimal getTrailingZeros(BigDecimal bd1) {
return bd1.stripTrailingZeros();
}
/**
* 返回一个BigDecimal,设置指定保留位数,及舍入策略
*/
public static BigDecimal getTargetScale(BigDecimal bd1,int numWei,int ceLue) {
return bd1.setScale(numWei,ceLue);
}
/**
* 返回BigDecimal和val的最大值,相等返回bd1
*/
public static BigDecimal getMaxBigDecimal(BigDecimal bd1,BigDecimal bd2) {
return bd1.max(bd2);
}
/**
* 返回BigDecimal和val的最小值,相等返回bd1
*/
public static BigDecimal getMinBigDecimal(BigDecimal bd1,BigDecimal bd2) {
return bd1.min(bd2);
}
/**
* 将该值的小数点移动n位到左边。如果n为非负,则调用仅将n添加至刻度。如果n为负时,调用相当于调用movePointRight(-n)。
*/
public static BigDecimal movePointLeftBigDecimal(BigDecimal bd,int num){
return bd.movePointLeft(num);
}
public static BigDecimal movePointRightBigDecimal(BigDecimal bd,int num){
return bd.movePointRight(num);
}
/**
* 看你是正数负数还是0
* 基于此BigDecimal返回这三个值[-1、1或0]中的任何一个
*/
public static int signumBigDecimal(BigDecimal bd){
return bd.signum();
}
/**
* BigDecimal转BigInteger
*/
public static BigInteger BigDecimalToBigInteger(BigDecimal decimal) {
return decimal.toBigInteger();
}
/**
* 最大公约数
* @return
*/
public static BigInteger bigIntegerGcd(BigInteger bigInteger1, BigInteger bigInteger2) {
return bigInteger1.gcd(bigInteger2);
}
/**
* 如果BigInteger可能是质数,则返回true,如果绝对是合数则返回false。如果确定性≤0,则返回true
*/
public static boolean BigIntegerIsProbablePrime(BigInteger integer) {
return integer.isProbablePrime(2);
}
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
/**
* BigDecimal、Double、String之间的互转
* 加减乘除的方法,都是重载方法,根据需求可扩容仿写即可(注意这块默认四舍五入策略,具体根需求修改)
* 提供BigDecimal、Double、String之间的精确的小数位四舍五入处理
* 两个数相除取余数
* 两个数比较大小
* <p>
* <p>
* 把阿拉伯数字转换为罗马数字:intToRomanNum
* 把罗马数字转换为阿拉伯数字:romanNumToInt
* int 转 中文数字:intTochineseNum(缺陷数字只能到亿)
* bigDecimal(包含小数点) 转中文数字 bigDecimalTochineseNum(缺陷整数数字只能到亿)
* 将任意长度的字符串str转换为中国传统金额表示方式:convertChineseNum (缺陷数字不支持小数)
* 及正常金额 convertHanNum (缺陷数字不支持小数)
* <p>
* 下面方法在使用时候先去看一下方法,返回特点是不是想要的
* BigDecimal货币格式化 currencyFormat
* BigDecimal百分比格式化 rateFormat
*/
public class BigDecimalArithmeticUtils {
private BigDecimalArithmeticUtils() {
}
//默认除法运算精度 保留10位小数
private static final int DEF_DIV_SCALE = 10;
/**
* BigDecimal转Double
*
* @param bigDecimal
* @return
*/
public static double BigDecimalToDouble(BigDecimal bigDecimal) {
return bigDecimal.doubleValue();
}
/**
* BigDecimal转String
*
* @param bigDecimal
* @return
*/
public static String BigDecimalToString(BigDecimal bigDecimal) {
return bigDecimal.toString();
}
/**
* Double转BigDecimal
*
* @param v
* @return
*/
public static BigDecimal DoubleToBigDecimal(double v) {
return new BigDecimal(Double.toString(v));
}
/**
* Double转String
*
* @param v
* @return
*/
public static String DoubleToString(double v) {
return Double.toString(v);
}
/**
* 提供精确的加法运算
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double addReturnDouble(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
public static BigDecimal add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2);
}
/**
* 提供精确的加法运算
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static BigDecimal add(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2);
}
/**
* 提供精确的加法运算
*
* @param v1 被加数
* @param v2 加数
* @param scale 保留scale 位小数
* @return 两个参数的和
*/
public static String add(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 精确的加法运算,并对运算结果截位.
*/
public static BigDecimal add(BigDecimal b1, BigDecimal b2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
public static String add(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的减法运算
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double subReturnDouble(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
public static BigDecimal sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2);
}
/**
* 提供精确的减法运算。
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static BigDecimal sub(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2);
}
/**
* 提供精确的减法运算
*
* @param v1 被减数
* @param v2 减数
* @param scale 保留scale 位小数
* @return 两个参数的差
*/
public static String sub(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
public static String sub(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
public static BigDecimal sub(BigDecimal v1, BigDecimal v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
return v1.subtract(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mulReturnDouble(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
public static BigDecimal mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2);
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static BigDecimal mul(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2);
}
public static BigDecimal mul(BigDecimal v1, BigDecimal v2) {
return v1.multiply(v2);
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 保留scale 位小数
* @return 两个参数的积
*/
public static double mul(double v1, double v2, int scale) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return round(b1.multiply(b2).doubleValue(), scale);
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 保留scale 位小数
* @return 两个参数的积
*/
public static String mul(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
public static BigDecimal mul(BigDecimal v1, BigDecimal v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
return v1.multiply(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入
*
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return divReturnDouble(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double divReturnDouble(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static BigDecimal divide(BigDecimal b1, BigDecimal b2) {
return b1.divide(b2);
}
public static BigDecimal div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal div(BigDecimal v1, BigDecimal v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
return v1.divide(v2, scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示需要精确到小数点以后几位
* @return 两个参数的商
*/
public static String div(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v1);
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static BigDecimal round(BigDecimal v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
return v.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static String round(String v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(v);
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数
*
* @param v1 被除数
* @param v2 除数
* @param scale 小数点后保留几位
* @return 余数
*/
public static String remainder(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
public static String remainder(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数 BigDecimal
*
* @param v1 被除数
* @param v2 除数
* @param scale 小数点后保留几位
* @return 余数
*/
public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 比较大小
*
* @param v1 被比较数
* @param v2 比较数
* @return 如果v1 大于v2 则 返回true 否则false
*/
public static boolean compare(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
int bj = b1.compareTo(b2);
boolean res;
if (bj > 0)
res = true;
else
res = false;
return res;
}
public static int compareInt(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.compareTo(b2);
}
public static boolean compare(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
int bj = b1.compareTo(b2);
boolean res;
if (bj > 0)
res = true;
else
res = false;
return res;
}
public static int compareInt(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.compareTo(b2);
}
public static boolean compare(BigDecimal v1, BigDecimal v2) {
int bj = v1.compareTo(v2);
boolean res;
if (bj > 0)
res = true;
else
res = false;
return res;
}
//比较BigDecimal,相等返回0,v1>v2 返回1, v1<v2 返回-1
public static int compareInt(BigDecimal v1, BigDecimal v2) {
return v1.compareTo(v2);
}
//建立货币格式化引用
private static final NumberFormat currency = NumberFormat.getCurrencyInstance();
/**
* "10042356.325354" ===> ¥10,042,356.33 100456 ===> ¥100,456.00
* BigDecimal货币格式化 currencyFormat
*
* @param money
* @return
*/
public static String currencyFormat(BigDecimal money) {
return currency.format(money);
}
/**
* 将数字转换成带逗号的字符串("###,##0.## ")
* @param reg 格式化串
* @param number 需要转换的数字
* @return
*/
public static String numberFormart(String reg,double number){
DecimalFormat bf = new DecimalFormat(reg);
return bf.format(number);
}
//建立百分比格式化引用
private static final NumberFormat percent = NumberFormat.getPercentInstance();
/**
* BigDecimal百分比格式化
* 0.12 ====>12% 1.4 ===>140%
* 0.005 ==> 0% 0.015==>2% 0.1445==>14%
* @param rate
* @return
*/
public static String rateFormat(BigDecimal rate) {
return percent.format(rate);
}
/**
* double类型的数字转化为百分之
*
* @param doubleNum
* double类型
* @return eg:类似21%的百分之
*/
public static String double2Percent(double doubleNum) {
DecimalFormat df = new DecimalFormat("##.00%");
if (doubleNum == 0.0)
return "0%";
return df.format(doubleNum);
}
public static String double2Percent(BigDecimal doubleNum) {
DecimalFormat df = new DecimalFormat("##.00%");
// if (doubleNum == 0.0)
// return "0%";
return df.format(doubleNum);
}
public static String double2Percent(String doubleNum) {
DecimalFormat df = new DecimalFormat("##.00%");
// if (doubleNum == 0.0)
// return "0%";
return df.format(doubleNum);
}
/**
* 把阿拉伯数字转换为罗马数字 intToRomanNum
* 罗马数字是古罗马使用的数字系统,现今仍很常见。罗马数字共有7个,
* 即Ⅰ(1),Ⅴ(5),Ⅹ(10),Ⅼ(50),Ⅽ(100),Ⅾ(500),Ⅿ(1000)。
* 需要注意的是罗马数字中没有“0”。
*
* @param number
* @return 小于1大于3999 返回-1
*/
public static String intToRomanNum(int number) {
String rNumber = "";
int[] aArray = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
String[] rArray = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X",
"IX", "V", "IV", "I"};
if (number < 1 || number > 3999) {
rNumber = "-1";
} else {
for (int i = 0; i < aArray.length; i++) {
while (number >= aArray[i]) {
rNumber += rArray[i];
number -= aArray[i];
}
}
}
return rNumber;
}
/**
* 把罗马数字转换为阿拉伯数字
*
* @param m
* @return
*/
public static int romanNumToInt(String m) {
int graph[] = new int[400];
graph['I'] = 1;
graph['V'] = 5;
graph['X'] = 10;
graph['L'] = 50;
graph['C'] = 100;
graph['D'] = 500;
graph['M'] = 1000;
char[] num = m.toCharArray();
int sum = graph[num[0]];
for (int i = 0; i < num.length - 1; i++) {
if (graph[num[i]] >= graph[num[i + 1]]) {
sum += graph[num[i + 1]];
} else {
sum = sum + graph[num[i + 1]] - 2 * graph[num[i]];
}
}
return sum;
}
/**
* 中文数字
*/
private static final String[] CN_NUM = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
/**
* 中文数字单位
*/
private static final String[] CN_UNIT = {"", "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千"};
/**
* 特殊字符:负
*/
private static final String CN_NEGATIVE = "负";
/**
* 特殊字符:点
*/
private static final String CN_POINT = "点";
/**
* int 转 中文数字
* 支持到int最大值
*
* @param intNum 要转换的整型数
* @return 中文数字
*/
public static String intTochineseNum(int intNum) {
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer();
int intNum2 = intNum;
boolean isNegative = false;
if (intNum < 0) {
isNegative = true;
intNum *= -1;
}
int count = 0;
while (intNum > 0) {
sb.insert(0, CN_NUM[intNum % 10] + CN_UNIT[count]);
intNum = intNum / 10;
count++;
}
if (isNegative)
sb.insert(0, CN_NEGATIVE);
// 10-19时,得到十~十九而不是一十~一十九
sb = "一".equals(sb.substring(0, 1)) && intNum2 < 100 && intNum2 > 1 ? sb2.append(sb.substring(1, sb.length())) : sb;
return sb.toString().replaceAll("零[千百十]", "零").replaceAll("零+万", "万")
.replaceAll("零+亿", "亿").replaceAll("亿万", "亿零")
.replaceAll("零+", "零").replaceAll("零$", "");
}
/**
* bigDecimal 转 中文数字 bigDecimalTochineseNum
* 整数部分只支持到int的最大值
*
* @param bigDecimalNum 要转换的BigDecimal数
* @return 中文数字
*/
public static String bigDecimalTochineseNum(BigDecimal bigDecimalNum) {
if (bigDecimalNum == null)
return CN_NUM[0];
StringBuffer sb = new StringBuffer();
//将小数点后面的零给去除
String numStr = bigDecimalNum.abs().stripTrailingZeros().toPlainString();
String[] split = numStr.split("\.");
String integerStr = intTochineseNum(Integer.parseInt(split[0]));
sb.append(integerStr);
//如果传入的数有小数,则进行切割,将整数与小数部分分离
if (split.length == 2) {
//有小数部分
sb.append(CN_POINT);
String decimalStr = split[1];
char[] chars = decimalStr.toCharArray();
for (int i = 0; i < chars.length; i++) {
int index = Integer.parseInt(String.valueOf(chars[i]));
sb.append(CN_NUM[index]);
}
}
//判断传入数字为正数还是负数
int signum = bigDecimalNum.signum();
if (signum == -1) {
sb.insert(0, CN_NEGATIVE);
}
return sb.toString();
}
/**
* 将任意长度的字符串str转换为中国传统金额表示方式,打印到控制台上
* 金额转换,阿拉伯数字转换成中国传统形式。
* 例如:101000001010 转换为 壹仟零壹拾亿零壹仟零壹拾圆整
* 注意:00101000000010等价101000000010 去除非法零
* 本题实现比较复杂,主要是对连续的零的判断,通过循环判断每一位及前一位是否为零,来控制是否删除多余的零。
* 实现了对任意长度的字符串的金额转换。
*/
public static String convertChineseNum(String str) {
//使用正则表达式判断字符串格式是否为数字格式
if (!str.matches("\d+")) {
return "字符串" + str + "不是数字格式,无法转换!";
}
//将字符串最前面的0去掉
while (str.startsWith("0")) {
str = str.substring(1, str.length());
}
//将字符串数字替换成中文数字
char[] num = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
char[] cnNum = new char[]{'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
for (int i = 0; i < 10; i++) {
str = str.replace(num[i], cnNum[i]);
}
StringBuilder sb = new StringBuilder(str);//StringBuilder存放字符串,用于插入删除操作
int index = str.length() - 1; //从第index个字符从后往前开始操作,操作一次,index--
//存放金额单位
String[] unit = {"", "拾", "佰", "仟"};
String[] unit4 = {"万", "亿"};
boolean flag = false;//判断前一个数是否为零的标记
for (int i = 0; i < str.length(); i++) {//循环体内对sb进行操作
//每4位插入万每8位插入亿,最低位先不设置单位
if (i % 4 == 0 && i != 0) {
//根据金额规则,单位万前面为4个零时,不插入万,并将index位置(最低位)的零删除
if ((i / 4 - 1) % 2 == 0 && index >= 3 && str.substring(index - 3, index + 1).equals("零零零零")) {
sb.deleteCharAt(index);
index--;
continue;
}
//否则在index+1位置插入相应的单位:万、亿
sb.insert(index + 1, unit4[(i / 4 - 1) % 2]);
}
//如果4位的最低位为零,删除最低位的零,将零标志置为true
if (i % 4 == 0 && str.charAt(index) == '零') {
sb.deleteCharAt(index);
flag = true;
index--;
continue;
}
//如果前一位为零并且这一位也为零,删除这一位的零
if (flag && str.charAt(index) == '零') {
sb.deleteCharAt(index);
index--;
continue;
}
//如果当前位为零,将零标志置为true
if (str.charAt(index) == '零') {
flag = true;
index--;
continue;
}
//当前位不为零,将零标志位置为false,插入金额单位
flag = false;
sb.insert(index + 1, unit[i % 4]);
index--;
}
//完善金额表示形式
sb.append("圆整");
return sb.toString();
}
public static String convertHanNum(String str) {
//使用正则表达式判断字符串格式是否为数字格式
if (!str.matches("\d+")) {
return "字符串" + str + "不是数字格式,无法转换!";
}
//将字符串最前面的0去掉
while (str.startsWith("0")) {
str = str.substring(1, str.length());
}
//将字符串数字替换成中文数字
char[] num = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
char[] cnNum = new char[]{'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'};
for (int i = 0; i < 10; i++) {
str = str.replace(num[i], cnNum[i]);
}
StringBuilder sb = new StringBuilder(str);//StringBuilder存放字符串,用于插入删除操作
int index = str.length() - 1; //从第index个字符从后往前开始操作,操作一次,index--
//存放金额单位
String[] unit = {"", "十", "百", "千"};
String[] unit4 = {"万", "亿"};
boolean flag = false;//判断前一个数是否为零的标记
for (int i = 0; i < str.length(); i++) {//循环体内对sb进行操作
//每4位插入万每8位插入亿,最低位先不设置单位
if (i % 4 == 0 && i != 0) {
//根据金额规则,单位万前面为4个零时,不插入万,并将index位置(最低位)的零删除
if ((i / 4 - 1) % 2 == 0 && index >= 3 && str.substring(index - 3, index + 1).equals("零零零零")) {
sb.deleteCharAt(index);
index--;
continue;
}
//否则在index+1位置插入相应的单位:万、亿
sb.insert(index + 1, unit4[(i / 4 - 1) % 2]);
}
//如果4位的最低位为零,删除最低位的零,将零标志置为true
if (i % 4 == 0 && str.charAt(index) == '零') {
sb.deleteCharAt(index);
flag = true;
index--;
continue;
}
//如果前一位为零并且这一位也为零,删除这一位的零
if (flag && str.charAt(index) == '零') {
sb.deleteCharAt(index);
index--;
continue;
}
//如果当前位为零,将零标志置为true
if (str.charAt(index) == '零') {
flag = true;
index--;
continue;
}
//当前位不为零,将零标志位置为false,插入金额单位
flag = false;
sb.insert(index + 1, unit[i % 4]);
index--;
}
return sb.toString();
}
}
BigDecimal的toString()方法和toPlainString()方法
今天遇到个问题 税率竟然采取了科学计数法,该数据类型是BigDecimal 通过 toString转成String类型的。后来换成toPlainString()方法进行解决的,下面分析一下
toString方法会将BigDecimal的值以科学计数方式的字符串
但是转换成科学计数的方式也是有场景的,并不是所有的值都会转为科学计数方式的字符串。
首先,任何一个BigDecimal都可以使用一个公式表示: unscaledValue × 10-scale
unscaledValue :整数非标度值 (即去掉小数点的Bigdecimal的值,类型为BigInteger)
scale:标度值,如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。
toPlainString()方法是一个非静态方法,仅可通过类对象访问,如果尝试使用类名访问该方法,则会收到错误消息。原值输出为字符串
String str1 = "12E+5";
String str2 = "1200000";
BigDecimal b_dec1 = new BigDecimal(str1);
BigDecimal b_dec2 = new BigDecimal(str2);
String str_conv = b_dec1.toPlainString();//1200000
str_conv = b_dec2.toPlainString();//1200000
String str3 = "12E+5";
String str4 = "-12000000";
BigDecimal b_dec1 = new BigDecimal(str3);
BigDecimal b_dec2 = new BigDecimal(str4);
//scale: -5 unscaledValue:12 toString:1.2E+6
System.out.println("scale: "+b_dec1.scale()+" unscaledValue:"+b_dec1.unscaledValue()+" toString:"+b_dec1.toString());
//scale: 0 unscaledValue:-12000000 toPlainString:-12000000
System.out.println("scale: "+b_dec2.scale()+" unscaledValue:"+b_dec2.unscaledValue()+" toPlainString:"+b_dec2.toString());
当我们使用BigDecimal转成字符串时,大多其实是想单纯的使用toString方法,而并不想使用科学计数的方式,所以应该使用的是toPlainString方法
.stripTrailingZeros()会造成科学计数,也是我工作实际中遇到的,
//一般直接使用 BigDecimal.toString()方法即可以完成浮点数的打印。
System.out.println(new BigDecimal("10000000000").toString());//10000000000
//但是,toString()方法输出的字符串并不能保证不是科学计数法。
//不过在日常的使用中,用toString()方法输出的就是普通的数字字符串而非科学计数法。
System.out.println( new BigDecimal("100.000").toString());//程序的输出即为: 100.000
// 如果我们希望去除末尾多余的0,那么我们应该这么写:
System.out.println( new BigDecimal("100.000").stripTrailingZeros().toString());
//其中,stripTrailingZeros()函数就是用于去除末尾多余的0的,但是此时程序的输出为: 1E+2
// 是科学计数法,可能并不是我们想要的。
//解决的方法很简单,如果想要避免输出科学计数法的字符串,我们要用toPlainString()函数代替toString()。如:
System.out.println( new BigDecimal("100.000").stripTrailingZeros().toPlainString());
BigDecimal 返回前端保留小数点后两位问题解决
现象就是,BigDecimal类型的字段,我已经格式化保留两位小数了,
我通过DeBug看返回的也是带小数的 比如 100.00 但是到了前端页面 看返回的确实100
后端返回 decimal 类型 100.00 到前端 会变成100 如何解决呢?
加注解:@JsonFormat(shape = JsonFormat.Shape.STRING)
备注:注解可以加在属性上或get方法上(我是加在属性上了,亲测可用)
如果你只是加在字段属性值上,那你返回给前端的时候需要 重新set该字段,给它格式化你想要的保留位数即可,
最后
以上就是默默纸飞机为你收集整理的Java中BigDecimal类常用方法,舍入策略Java BigDecimal 的舍入模式 (RoundingMode)详解提一下银行家算法BigDecimal和BigIntegerJava中BigDecimal常用方法BigDecimal的toString()方法和toPlainString()方法的全部内容,希望文章能够帮你解决Java中BigDecimal类常用方法,舍入策略Java BigDecimal 的舍入模式 (RoundingMode)详解提一下银行家算法BigDecimal和BigIntegerJava中BigDecimal常用方法BigDecimal的toString()方法和toPlainString()方法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复