将数字转为中文金额的大写方式(Java版)

陈啊咧 2008-06-13 02:01:15

/**
* 程序目的:
* 从命令行接收一个数,并将其转化为中文金额的大写方式
* 例如 123.45 --> 壹佰贰拾叁元肆角伍分
* @author LovinChan
*
* 看到网上有很多这样的例子程序,不过觉得很不满意。有些程序我从命名上就觉得
* 实在是不符合规范,程序里面的算法没有让人明白得很清楚的注释,读上去觉得有
* 点难度,可读性不强。而且很多程序还存在不少bug,随便一测就测出来了。
* 所以本人还是决定重新写一下这个程序,并且尽量做到消除不必要的bug。这个程
* 序我没有用什么很精妙的算法,不过用了一些Java类库中的类,像是正则表达式之类
* 的东西。由于本人对算法不怎么在行,在做转换操作的时候用的是很笨的方法。望各位
* 大虾海涵,呵呵。
*
* 程序的注释我尽量写得详细一点,如果觉得这个程序哪里有问题或者是哪里有改进的
* 地方欢迎随时跟我交流。
* 我的msn:egg.chenlw@gmail.com
* QQ:543669516(注上为什么加我就可以了)
* 我的blog:http://hi.baidu.com/egg_chen
* 欢迎交流
*/
public class Trans2RMB {

/**
* 测试程序的可行性
* @param args
*/
public static void main(String[] args) {
System.out.println("--------将数字转换成中文金额的大写形式------------\n");
Trans2RMB t2r = new Trans2RMB();
String s = t2r.cleanZero(t2r.splitNum(t2r.roundString(t2r.getNum())));
// 如果转换过后是一个空串,则不输出屏幕
if(!"".equals(s)) {
System.out.println("转换成中文后为:" + s);;
}
System.out.println("\n---------------------------------------------");
}

/**
* 从命令行接收一个数,在其中调用 checkNum() 方法对其进行
* 验证,并返回相应的值
* @return 如果输入合法,返回输入的这个数
*/
private String getNum() {
String s = null;
System.out.println("请输入一个数字(精确到小数点后两位):");
// 从命令行输入这个浮点数
java.util.Scanner scanner = new java.util.Scanner(System.in);
s = scanner.next();
// 判断用户输入是否合法
// 若合法,返回这个值;若非法返回 "0"
if(this.checkNum(s)) {
return s;
} else {
return "";
}
}

/**
* 判断用户输入的数据是否合法,用户只能输入大于零的数字,不能输入其它字符
* @param s String
* @return 如果用户输入数据合法,返回 true,否则返回 false
*/
private boolean checkNum(String s) {
// 如果用户输入的数里有非数字字符,则视为非法数据,返回 false
try {
float f = Float.valueOf(s);
// 如果这个数小于零则视为非法数据,返回 false
if(f < 0) {
System.out.println("非法数据,请检查!");
return false;
}else {
return true;
}
} catch (NumberFormatException e) {
System.out.println("非法数据,请检查!");
return false;
}
}

/**
* 把用户输入的数以小数点为界分割开来,并调用 numFormat() 方法
* 进行相应的中文金额大写形式的转换
* 注:传入的这个数应该是经过 roundString() 方法进行了四舍五入操作的
* @param s String
* @return 转换好的中文金额大写形式的字符串
*/
private String splitNum(String s) {
// 如果传入的是空串则继续返回空串
if("".equals(s)) {
return "";
}
// 以小数点为界分割这个字符串
int index = s.indexOf(".");
// 截取并转换这个数的整数部分
String intOnly = s.substring(0, index);
String part1 = this.numFormat(1, intOnly);
// 截取并转换这个数的小数部分
String smallOnly = s.substring(index + 1);
String part2 = this.numFormat(2, smallOnly);
// 把转换好了的整数部分和小数部分重新拼凑一个新的字符串
String newS = part1 + part2;
return newS;
}

/**
* 对传入的数进行四舍五入操作
* @param s String 从命令行输入的那个数
* @return 四舍五入后的新值
*/
private String roundString(String s) {
// 如果传入的是空串则继续返回空串
if("".equals(s)) {
return "";
}
// 将这个数转换成 double 类型,并对其进行四舍五入操作
double d = Double.parseDouble(s);
// 此操作作用在小数点后两位上
d = (d * 100 + 0.5) / 100;
// 将 d 进行格式化
s = new java.text.DecimalFormat("##0.000").format(d);
// 以小数点为界分割这个字符串
int index = s.indexOf(".");
// 这个数的整数部分
String intOnly = s.substring(0, index);
// 规定数值的最大长度只能到万亿单位,否则返回 "0"
if(intOnly.length() > 13) {
System.out.println("输入数据过大!(整数部分最多13位!)");
return "";
}
// 这个数的小数部分
String smallOnly = s.substring(index + 1);
// 如果小数部分大于两位,只截取小数点后两位
if(smallOnly.length() > 2) {
String roundSmall = smallOnly.substring(0, 2);
// 把整数部分和新截取的小数部分重新拼凑这个字符串
s = intOnly + "." + roundSmall;
}
return s;
}

/**
* 把传入的数转换为中文金额大写形式
* @param flag int 标志位,1 表示转换整数部分,0 表示转换小数部分
* @param s String 要转换的字符串
* @return 转换好的带单位的中文金额大写形式
*/
private String numFormat(int flag, String s) {
int sLength = s.length();
// 货币大写形式
String bigLetter[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
// 货币单位
String unit[] = {"元", "拾", "佰", "仟", "万",
// 拾万位到仟万位
"拾", "佰", "仟",
// 亿位到万亿位
"亿", "拾", "佰", "仟", "万"};
String small[] = {"分", "角"};
// 用来存放转换后的新字符串
String newS = "";
// 逐位替换为中文大写形式
for(int i = 0; i < sLength; i ++) {
if(flag == 1) {
// 转换整数部分为中文大写形式(带单位)
newS = newS + bigLetter[s.charAt(i) - 48] + unit[sLength - i - 1];
} else if(flag == 2) {
// 转换小数部分(带单位)
newS = newS + bigLetter[s.charAt(i) - 48] + small[sLength - i - 1];
}
}
return newS;
}

/**
* 把已经转换好的中文金额大写形式加以改进,清理这个字
* 符串里面多余的零,让这个字符串变得更加可观
* 注:传入的这个数应该是经过 splitNum() 方法进行处理,这个字
* 符串应该已经是用中文金额大写形式表示的
* @param s String 已经转换好的字符串
* @return 改进后的字符串
*/
private String cleanZero(String s) {
// 如果传入的是空串则继续返回空串
if("".equals(s)) {
return "";
}
// 如果用户开始输入了很多 0 去掉字符串前面多余的'零',使其看上去更符合习惯
while(s.charAt(0) == '零') {
// 将字符串中的 "零" 和它对应的单位去掉
s = s.substring(2);
// 如果用户当初输入的时候只输入了 0,则只返回一个 "零"
if(s.length() == 0) {
return "零";
}
}
// 字符串中存在多个'零'在一起的时候只读出一个'零',并省略多余的单位
/* 由于本人对算法的研究太菜了,只能用4个正则表达式去转换了,各位大虾别介意哈... */
String regex1[] = {"零仟", "零佰", "零拾"};
String regex2[] = {"零亿", "零万", "零元"};
String regex3[] = {"亿", "万", "元"};
String regex4[] = {"零角", "零分"};
// 第一轮转换把 "零仟", 零佰","零拾"等字符串替换成一个"零"
for(int i = 0; i < 3; i ++) {
s = s.replaceAll(regex1[i], "零");
}
// 第二轮转换考虑 "零亿","零万","零元"等情况
// "亿","万","元"这些单位有些情况是不能省的,需要保留下来
for(int i = 0; i < 3; i ++) {
// 当第一轮转换过后有可能有很多个零叠在一起
// 要把很多个重复的零变成一个零
s = s.replaceAll("零零零", "零");
s = s.replaceAll("零零", "零");
s = s.replaceAll(regex2[i], regex3[i]);
}
// 第三轮转换把"零角","零分"字符串省略
for(int i = 0; i < 2; i ++) {
s = s.replaceAll(regex4[i], "");
}
// 当"万"到"亿"之间全部是"零"的时候,忽略"亿万"单位,只保留一个"亿"
s = s.replaceAll("亿万", "亿");
return s;
}
}
...全文
1792 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ljc821 2008-06-13
  • 打赏
  • 举报
回复
楼上的意思是把中文金额大写转换为阿拉伯数字吗?这个问题应该很简单的。字符“圆”把大写分为两个部分,即整数部分和小数部分(小数部分可能没有)。整数部分通过“兆”、“亿”、“万”等单位符号把中文金额分为若干个部分,每部分的数值范围是0-9999的中文大写。这部分的数字转换非常容易,然后把每部分的数值乘以相应的单位代表的数值(比如万代表10000),相加之后的结果即为整数部分的数据。小数部分一般只有两位,就不必说了吧。思路很简单,可能写程序的时候要注意一些细节问题。
cpoysy 2008-06-13
  • 打赏
  • 举报
回复
呵呵....如果是繁体操作系统呢?
zixiakoma 2008-06-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 java2000_net 的回复:]
我博客有现成的类
[/Quote]

紫竹大哥面试华为如何了,不该发这里,呵呵。
shadowlin 2008-06-13
  • 打赏
  • 举报
回复
有人可以写个比较可靠的把中文数字转阿拉伯的么?
老紫竹 2008-06-13
  • 打赏
  • 举报
回复
我博客有现成的类
ljc821 2008-06-13
  • 打赏
  • 举报
回复
自己写的一个大写装换类,集思广益,共享一下:)

/**
* @author Jason
*
*/
public class DaxieUtil {
/**
* 阿拉伯数字对应的汉字大写字符集合.
*/
private static char[] N = new char[] { '零', '壹', '贰', '叁', '肆', '伍', '陆',
'柒', '捌', '玖' };

/**
* 基本单位字符集合.
*/
private static char[] U = new char[] { '拾', '佰', '仟' };

/**
* 特殊单位字符集合.
*/
private static char[] X = new char[] { '万', '亿', '兆' };

/**
*
* @param d
* @return
*/
public static String toDaxie(double d) {
if (d <= 0)
return "";
if (d > Long.MAX_VALUE)
throw new IllegalArgumentException("参数超出长整数的最大支持范围!");
String str = rawProcess(d);
StringBuffer result = postProcess(d, str);
fractionProcess(d, result);
return result.toString();
}

/**
* 小数部分处理.
*
* @param d
* @param result
*/
private static void fractionProcess(double d, StringBuffer result) {
if (d % 1 > 0) {// 处理小数部分, 仅支持两位小数
int fraction = ((int) (d * 100)) % 100;
if (fraction / 10 != 0) {
result.append(N[fraction / 10] + "角");
}
if (fraction % 10 != 0) {
result.append(N[fraction % 10] + "分");
}
} else {// 如果沒有小数, 尾部为'整'
result.append("整");
}
}

/**
* 后处理过程, 处理为惯用法.
*
* @param d
* @param str
* @return
*/
private static StringBuffer postProcess(double d, String str) {
StringBuffer result = new StringBuffer();
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == N[0]) {// 处理为惯用用法
if (i < chars.length - 1) {
int ignoreType = 0;
for (int j = 0; j < U.length; j++) {// 处理诸如'零仟', '零佰',
// '零拾'等情况
if (chars[i + 1] == U[j]) {
ignoreType = -1;
break;
}
}
for (int j = 0; j < X.length; j++) {// 处理诸如'零亿','零万'等情况
if (chars[i + 1] == X[j]) {
ignoreType = 1;
break;
}
}
final int length = result.length();
switch (ignoreType) {
case -1:
// 保证不输出相邻重复的'零', 跳过'零'后的单位符号
i++;
if (length > 0 && result.charAt(length - 1) != N[0])
result.append(N[0]);
break;
case 1:
// 如果单位'万','亿','兆'前面出现'零',则删除'零'
i++;
if (length > 0 && result.charAt(length - 1) == N[0])
result.deleteCharAt(length - 1);
char v = result.charAt(result.length() - 1);
boolean append = true;
for (int j = 0; j < X.length; j++) {// 处理诸如'亿万'的情况
if (v == X[j]) {
append = false;
break;
}
}
if (append)
result.append(chars[i]);
break;
}
}
} else {
result.append(c);
}
}
// 处理最后一个字符是'零'的情况
int len = result.length();
if (len > 0 && result.charAt(len - 1) == N[0]) {
result.deleteCharAt(len - 1);
}
result.append('圆');
return result;
}

/**
*
* @param d
* @return
*/
private static String rawProcess(double d) {
StringBuffer buf = new StringBuffer();
long n = (long) d;
int bit = 0;
int x = 0;
while (n > 0) {
int m = (int) (n % 10);// 最低位数字
buf.append(N[m]);
n = n / 10;
if (n > 0) {
int index = bit % 4;
if (index == 3)
buf.append(X[x++]);
else
buf.append(U[index]);
}
bit++;
}
return buf.reverse().toString();
}

}

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧