Java数字⾦额⼤写转换
最初(来⾃CSDN,看到的也是转载贴,未注明出处,侵删)
其实这种⼯具类⽹上有很多,但个⼈感觉这个逻辑更加清晰,所以后⾯都是在这版的基础是进⾏修改
public class ConvertNumberToUpper {
/**
* 数字⾦额⼤写转换,思想先写个完整的然后将如零拾替换成零要⽤到正则表达式
*/
public static String digitUppercase(double n){
String fraction[]={"⾓","分"};
String digit[]={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
String unit[][]={{"元","万","亿"},{"","拾","佰","仟"}};
String head = n <0?"负":"";
// 如果是负数取绝对值
n = Math.abs(n);
// ⼩数部分
String s ="";
for(int i =0; i < fraction.length; i++){
// Math.floor(a)返回⼤于或等于参数的最⼩(最接近负⽆穷⼤) double值,并等于数学整数,Math.pow(10, i)10的i次幂
s +=(digit[(int)(Math.floor(n * Math.pow(10, i +1))%10)]+ fraction[i]).replaceAll("(零.)+","");
}
if(s.length()<1){
s ="整";
}
int integerPart =(int)Math.floor(n);
// 整数部分
for(int i =0; i < unit[0].length && integerPart >0; i++){
String p ="";
for(int j =0; j < unit[1].length && n >0; j++){
p = digit[integerPart %10]+ unit[1][j]+ p;
integerPart = integerPart /10;
}
s = p.replaceAll("(零.)*零$","").replaceAll("^$","零")+ unit[0][i]+ s;
}
return head + s.replaceAll("(零.)*零元","元").replaceFirst("(零.)+","").replaceAll("(零.)+","零").replaceAll("^整$","零元整");
}
}
⾃⼰测试发现能满⾜业务需要,所以就直接拿来主义了!
后⾯⾃⼰review时发现原贴下⾯的⼀条评论是这样的
Math.floor(n * 10 * Math.pow(10, i)) % 10)第⼀个⽅法⾥⾯,是否会因为double*10精度问题进⾏取整导致数据不正确? ⽐如40899.84 * 10的double值408998.39999999…向下取整只会取到3,正好碰到了这个问题
通过mian⽅法测试发现确实存在这个问题
public static void main(String[] args){
// 这⾥使⽤与System.out没有区别,只是会⽤红⾊字体显⽰,可以很清晰的看出与⽇志的区别,强烈建议在测试的时候使⽤
}
输出结果:肆万零捌佰玖拾玖元捌⾓叁分
原因:Java中浮点类型运算会产⽣精度问题(⼆进制浮点运算引起)
尝试解决问题,思路是既然只有⼩数部分有问题就把⼩数部分截取后转换成整数处理
public class ConvertNumberToUpper {
public static String digitCapital(double n){
String fraction[]={"⾓","分"};
String digit[]={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
String unit[][]={{"元","万","亿"},{"","拾","佰","仟"}};
String head = n <0?"负":"";
/
/ 如果是负数取绝对值
n = Math.abs(n);
String s ="";
// 由于n为double类型,所以整数如100转换后变为100.0
String nStr = n +"";
// ⼩数部分,⼩数点为特殊符号,在分割时需进⾏转义
String split = nStr.split("\\.")[1];
// 如果⼩数部分只有⼀位且为0,直接舍弃
if(!(split.length()==1&&"0".equals(split))){
// 只精确到⼩数点后两位
if(split.length()>2){
split = split.substring(0,2);
}
// 将⼩数部分转换为整数
Integer integer = Integer.valueOf(split);
String p ="";
for(int i =0; i < split.length()&& i < fraction.length; i++){
p = digit[integer %10]+ fraction[split.length()- i -1]+ p;
integer = integer /10;
}
s = p.replaceAll("(零.)+","")+ s;
}
if(s.length()<1){
s ="整";
}
int integerPart =(int)Math.floor(n);
// 整数部分
for(int i =0; i < unit[0].length && integerPart >0; i++){
String p ="";
for(int j =0; j < unit[1].length && n >0; j++){
p = digit[integerPart %10]+ unit[1][j]+ p;
integerPart = integerPart /10;
}
s = p.replaceAll("(零.)*零$","").replaceAll("^$","零")+ unit[0][i]+ s;
}
return head + s.replaceAll("(零.)*零元","元").replaceFirst("(零.)+","").replaceAll("(零.)+","零").replaceAll("^整$","零元整"); }
测试发现解决了上⾯的问题
然⽽⼜发现新的问题
public static void main(String[] args){
}
输出结果:肆仟捌拾万零玖拾玖元捌分
这是因为java中对过⼤的数据采⽤科学计数法表⽰,debug会发现传到⽅法中的n已经变为4.080009984E7
然后就是解决问题了,思路就是不使⽤科学计数法表⽰数据
查资料发现有两种⽅式实现
// ⽅法⼀
NumberFormat nf = Instance();
nf.setGroupingUsed(false);
String nStr = nf.format(n);
//⽅法⼆
BigDecimal bigDecimal =new BigDecimal(Double.valueOf(n).toString()); String nStr = String();
通过下⾯简单测试,发现⽅法⼆的效率明显要好于⽅法⼀
String head = n <0?"负":"";
// 如果是负数取绝对值
n = Math.abs(n);
String s ="";
BigDecimal bigDecimal =new BigDecimal(Double.valueOf(n).toString());
String nStr = String();
// NumberFormat nf = Instance();
// nf.setGroupingUsed(false);
// String nStr = nf.format(n);
// 由于n为double类型,所以整数如100转换后变为100.0
/
/ ⼩数部分
String[] split = nStr.split("\\.");
if(split.length >1){
// ⼩数点为特殊符号,在分割时需进⾏转义
String decimalStr = split[1];
if(decimalStr.length()>2){
decimalStr = decimalStr.substring(0,2);
}
// 将⼩数部分转换为整数
Integer integer = Integer.valueOf(decimalStr);
String p ="";
for(int i =0; i < decimalStr.length()&& i < fraction.length; i++){
p = digit[integer %10]+ fraction[decimalStr.length()- i -1]+ p;
integer = integer /10;
}
s = p.replaceAll("(零.)+","")+ s;
}
if(s.length()<1){
s ="整";
}
int integerPart =(int)Math.floor(n);
// 整数部分
for(int i =0; i < unit[0].length && integerPart >0; i++){
String p ="";
for(int j =0; j < unit[1].length && n >0; j++){
p = digit[integerPart %10]+ unit[1][j]+ p;
integerPart = integerPart /10;
}
s = p.replaceAll("(零.)*零$","").replaceAll("^$","零")+ unit[0][i]+ s;
}
return head + s.replaceAll("(零.)*零元","元").replaceFirst("(零.)+","").replaceAll("(零.)+","零").replaceAll("^整$","零元整"); }
public static void main(String[] args){
long t1 = System.currentTimeMillis();
long t2 = System.currentTimeMillis();
long t3 = System.currentTimeMillis();
long t4 = System.currentTimeMillis();
}
最终版
String head = n <0?"负":"";
// 如果是负数取绝对值
n = Math.abs(n);
String s ="";
BigDecimal bigDecimal =new BigDecimal(Double.valueOf(n).toString());
String nStr = String();
// ⼩数部分
String[] split = nStr.split("\\.");
if(split.length >1){
// ⼩数点为特殊符号,在分割时需进⾏转义
String decimalStr = split[1];
if(decimalStr.length()>2){
decimalStr = decimalStr.substring(0,2);
}
// 将⼩数部分转换为整数
Integer integer = Integer.valueOf(decimalStr);
String p ="";
for(int i =0; i < decimalStr.length()&& i < fraction.length; i++){
p = digit[integer %10]+ fraction[decimalStr.length()- i -1]+ p;
integer = integer /10;
}
s = p.replaceAll("(零.)+","")+ s;
}
if(s.length()<1){
java valueofs ="整";
}
int integerPart =(int)Math.floor(n);
// 整数部分
for(int i =0; i < unit[0].length && integerPart >0; i++){
String p ="";
for(int j =0; j < unit[1].length && n >0; j++){
p = digit[integerPart %10]+ unit[1][j]+ p;
integerPart = integerPart /10;
}
s = p.replaceAll("(零.)*零$","").replaceAll("^$","零")+ unit[0][i]+ s;
}
return head + s.replaceAll("(零.)*零元","元").replaceFirst("(零.)+","").replaceAll("(零.)+","零").replaceAll("^整$","零元整"); }
注意:Integer的取值范围是从-2147483648 ⾄ 214748364,超过该范围就会按最⼤值计算
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论