本人是从事互联网金融行业的,所以会接触到一些金融类的问题,常见的一种就是数字转汉字大小写的问题。所以抽空就写了一个小小的工具类,实现了数字转汉字、大数相加、相减、相乘的工具类,希望能帮助有需求的同行们。本篇就分享一下数字转化为汉字的思路吧。
数字转汉字的原理:
- 拆分:由于整数部分要加权值,而小数部分直接转换即可,所以首先要将数字拆分成整数+小数;
- 整数处理:按照我们的中国人的习惯,把数字格式化成4位一组,不足4位前面补0。每次处理4位,按位匹配数组中的汉字+权值。即按照数值找数字数组(num_lower 、num_upper )中对应位置的汉字,按照在4位中的偏移量在单位权值数组(unit_lower 、unit_upper )中找。比如21,转化4位为0021,前面的0不用管,2对应数字“二”,权值是“十”,1对应数字“一”,权值是“(个)”用空字符串代替。即得到“二十一”。每4位处理完后,还要整体对应一个权值,比如“万、亿、兆”等;
- 小数处理:小数部分直接按位对应汉字数组和权值即可。
废话了这么多,可能云里雾里的,看看具体代码吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
//num 表示数字,lower表示小写,upper表示大写
private static final String[] num_lower = { "零" , "一" , "二" , "三" , "四" , "五" , "六" , "七" , "八" , "九" };
private static final String[] num_upper = { "零" , "壹" , "贰" , "叁" , "肆" , "伍" , "陆" , "柒" , "捌" , "玖" };
//unit 表示单位权值,lower表示小写,upper表示大写
private static final String[] unit_lower = { "" , "十" , "百" , "千" };
private static final String[] unit_upper = { "" , "拾" , "佰" , "仟" };
private static final String[] unit_common = { "" , "万" , "亿" , "兆" , "京" , "垓" , "秭" , "穰" , "沟" , "涧" , "正" , "载" };
//允许的格式
private static final List<String> promissTypes = Arrays.asList( "INTEGER" , "INT" , "LONG" , "DECIMAL" , "FLOAT" , "DOUBLE" , "STRING" , "BYTE" , "TYPE" , "SHORT" );
/**
* 数字转化为小写的汉字
*
* @param num 将要转化的数字
* @return
*/
public static String toChineseLower(Object num){
return format(num, num_lower, unit_lower);
}
/**
* 数字转化为大写的汉字
*
* @param num 将要转化的数字
* @return
*/
public static String toChineseUpper(Object num){
return format(num, num_upper, unit_upper);
}
/**
* 格式化数字
*
* @param num 原数字
* @param numArray 数字大小写数组
* @param unit 单位权值
* @return
*/
private static String format(Object num,String[] numArray,String[] unit){
if (!promissTypes.contains(num.getClass().getSimpleName().toUpperCase())){
throw new RuntimeException( "不支持的格式类型" );
}
//获取整数部分
String intnum = getInt(String.valueOf(num));
//获取小数部分
String decimal = getFraction(String.valueOf(num));
//格式化整数部分
String result = formatIntPart(intnum,numArray,unit);
if (! "" .equals(decimal)){ //小数部分不为空
//格式化小数
result += "点" +formatFractionalPart(decimal, numArray);
}
return result;
}
/**
* 格式化整数部分
*
* @param num 整数部分
* @param numArray 数字大小写数组
* @return
*/
private static String formatIntPart(String num,String[] numArray,String[] unit){
//按4位分割成不同的组(不足四位的前面补0)
Integer[] intnums = split2IntArray(num);
boolean zero = false ;
StringBuffer sb = new StringBuffer();
for ( int i= 0 ;i<intnums.length;i++){
//格式化当前4位
String r = formatInt(intnums[i], numArray,unit);
if ( "" .equals(r)){ //
if ((i+ 1 )==intnums.length){
sb.append(numArray[ 0 ]); //结果中追加“零”
} else {
zero= true ;
}
} else { //当前4位格式化结果不为空(即不为0)
if (zero || (i> 0 && intnums[i]< 1000 )){ //如果前4位为0,当前4位不为0
sb.append(numArray[ 0 ]); //结果中追加“零”
}
sb.append(r);
sb.append(unit_common[intnums.length- 1 -i]); //在结果中添加权值
zero= false ;
}
}
return sb.toString();
}
/**
* 格式化小数部分
*
* @param decimal 小数部分
* @param numArray 数字大小写数组
* @return
*/
private static String formatFractionalPart(String decimal,String[] numArray) {
char [] val = String.valueOf(decimal).toCharArray();
int len = val.length;
StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < len; i++) {
int n = Integer.valueOf(val[i] + "" );
sb.append(numArray[n]);
}
return sb.toString();
}
|
拆分整数和小数的方法在这里:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/**
* 获取整数部分
*
* @param num
* @return
*/
private static String getInt(String num){
//检查格式
checkNum(num);
char [] val = String.valueOf(num).toCharArray();
StringBuffer sb = new StringBuffer();
int t , s = 0 ;
for ( int i = 0 ; i < val.length; i++) {
if (val[i]== '.' ) {
break ;
}
t = Integer.parseInt(val[i]+ "" , 16 );
if (s+t== 0 ){
continue ;
}
sb.append(t);
s+=t;
}
return (sb.length()== 0 ? "0" :sb.toString());
}
/**
* 获取小数部分
*
* @param num
* @return
*/
private static String getFraction(String num){
int i = num.lastIndexOf( "." );
if (num.indexOf( "." ) != i){
throw new RuntimeException( "数字格式不正确,最多只能有一位小数点!" );
}
String fraction = "" ;
if (i>= 0 ){
fraction = getInt( new StringBuffer(num).reverse().toString());
if (fraction.equals( "0" )){
return "" ;
}
}
return new StringBuffer(fraction).reverse().toString();
}
/**
* 检查数字格式
*
* @param num
*/
private static void checkNum(String num) {
if (num.indexOf( "." ) != num.lastIndexOf( "." )){
throw new RuntimeException( "数字[" +num+ "]格式不正确!" );
}
if (num.indexOf( "-" ) != num.lastIndexOf( "-" ) || num.lastIndexOf( "-" )> 0 ){
throw new RuntimeException( "数字[" +num+ "]格式不正确!" );
}
if (num.indexOf( "+" ) != num.lastIndexOf( "+" )){
throw new RuntimeException( "数字[" +num+ "]格式不正确!" );
}
if (num.indexOf( "+" ) != num.lastIndexOf( "+" )){
throw new RuntimeException( "数字[" +num+ "]格式不正确!" );
}
if (num.replaceAll( "[\\d|\\.|\\-|\\+]" , "" ).length()> 0 ){
throw new RuntimeException( "数字[" +num+ "]格式不正确!" );
}
}
|
通过这种分而治之的思路,处理起来就简单多了。写个main函数调用一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public static void main(String[] args) {
short s = 10 ;
byte b= 10 ;
char c= 'A' ;
Object[] nums = {s, b, c, 0 , 1001 , 100100001L, 21 ., 205 .23F, 205 .23D, "01000010" , "1000000100105.0123" , ".142" , "20.00" , "1..2" , true };
System.out.println( "将任意数字转化为汉字(包括整数、小数以及各种类型的数字)" );
System.out.println( "--------------------------------------------" );
for (Object num :nums){
try {
System.out.print( "[" +num.getClass().getSimpleName()+ "]" +num);
for ( int i= 0 ;i< 25 -String.valueOf(num+num.getClass().getSimpleName()).length();i+= 4 ){
System.out.print( "\t" );
}
//调用转化为小写和大写
System.out.print( " format:" +toChineseLower(num));
System.out.println( "【" +toChineseUpper(num)+ "】" );
} catch (Exception e){
System.out.println( " 错误信息:" +e.getMessage());
}
}
}
|
看看结果吧:
从上述代码和运行结果中,我们可以看到该功能支持多种数据类型的转换、支持转化为一般汉字和财务专用大写汉字。还可以智能处理非正常逻辑的数字。比如“20”会转化为“二十”而非“二十零”;“1 0000 0001” 转换成“一亿零一”而非“一亿零万零一”。
这里只分享了一个转换汉字的功能,下篇将分享一下大数相乘、相加、相减的方法。支持小数和负数的运算,敬请期待。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://blog.csdn.net/xiaoxian8023/article/details/49834589