新手学JAVA,看到别人写的好多数字和汉字之间的转换,一时心痒痒,就写了一个可以实现中文汉语数字和阿拉伯数字、人民币大小写之间的互相转换,发出来供大家检验和参考。
我写的这个转换代码有以下几个特点:
1、转换没有限制:支持小数转换、支持正负数转换,无论多长的数字都能转换过来,前提是你的书写格式要正确;
2、转换比较全面,不仅有数字转换汉字,还有汉字转换数字,更有人民币大小写转换;
3、全部转换方法采用static修饰,方面其它类调用(直接用“类名+方法名”调用);
4、虽然代码较长,但是自我感觉充分考虑了性能,尽量减少字符串的使用,相信运行速度还是能接受的;
5、所有异常(一般是传入参数格式错误导致的)参数统一设置为IllegalArgumentException类异常,调试时可注释掉;
6、由于是新手,注释会不太规范,结构也不是很合理,或许很难看懂,也有可能会有不少BUG,一经发现我会及时更新。
欢迎大家提出宝贵的意见建议!
import java.util.HashMap;
import java.util.Map;
/**
* 工具类,用于汉语数字和阿拉伯数字、RMB大小写之间的相互转换;
* 阿拉伯数字转换汉语数字:String chinese = TranslateNumber.numberToChinese("-105.263");
* 汉语数字转换阿拉伯数字:String number = TranslateNumber.chineseToNumber("负一百零五点二六三");
* 人民币小写转换大写:String rmbWords = TranslateNumber.figuresToWords("15.23元");
* 人民币大写转换小写:String rmbFigures = TranslateNumber.wordsToFigures("壹拾伍元贰角叁分");
* @author ywfpclt@qq3462907
* @version 1.0
*/
public class TranslateNumber {
public static String numberToChinese(String in) {
/**
* 阿拉伯数字转换汉语数字
* @param 阿拉伯数字
* @return 汉语数字
*/
String[] ch = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
StringBuilder out = new StringBuilder();// 定义返回值变量
StringBuilder integer = new StringBuilder(in);// 定义整数部分,假设传入参数为整数
try {// 将所有异常统一设置为“传入参数错误”异常
if (in.indexOf('.') != -1) {// 判断是否存在小数
out.append(in.substring(in.indexOf('.') + 1));// 截取小数部分字符串
integer.delete(in.indexOf('.'), in.length());// 整数部分删除“.”及后面部分字符串
/**
* 分类转换小数部分
*/
for (int i = out.length() - 1; i >= 0; i--) {
if (i == out.length() - 1 && out.charAt(i) == '0') {
out.deleteCharAt(i);// 删除后缀“0”
} else {
out.setCharAt(i, ch[out.charAt(i) - '0'].charAt(0));
}
}
if (out.length() > 0) {
out.insert(0, '点');// 如果小数部分不为0则添加小数点
}
}
ch[0] = "";// 转换整数部分时“零”显示为空字符串
out.insert(0, numToCh(integer, ch));// 调用整数部分转换方法转换整数部分
} catch (Exception e) {
throw new IllegalArgumentException("For input string:" + in);
}
if (out.toString().equals("负零")) {
out.deleteCharAt(0);
}
return out.toString();
}
public static String chineseToNumber(String in) {
/**
* 汉语数字转换阿拉伯数字
* @param 汉语数字
* @return 阿拉伯数字
*/
Map<Character, Integer> nums = new HashMap<>();
nums.put('〇', 0);
nums.put('零', 0);
nums.put('一', 1);
nums.put('二', 2);
nums.put('三', 3);
nums.put('四', 4);
nums.put('五', 5);
nums.put('六', 6);
nums.put('七', 7);
nums.put('八', 8);
nums.put('九', 9);
StringBuilder out = new StringBuilder();// 定义返回值变量
StringBuilder integer = new StringBuilder(in);// 定义整数部分,假设传入参数为整数
try {// 将所有异常统一设置为“传入参数错误”异常
if (in.indexOf('点') != -1) {// 判断是否存在小数
out.append(in.substring(in.indexOf('点') + 1));// 截取小数部分字符串
integer.delete(in.indexOf('点'), in.length());// 整数部分删除“点”及后面部分字符串
/**
* 转换小数部分
*/
for (int i = out.length() - 1; i >= 0; i--) {
if (i == out.length() - 1 && out.charAt(i) == '零') {
out.deleteCharAt(i);// 删除后缀“0”
} else {
out.setCharAt(i, (char) (nums.get(out.charAt(i)) + '0'));
}
}
if (out.length() > 0) {
out.insert(0, '.');// 如果小数部分不为0则添加小数点
}
}
out.insert(0, chToNum(integer, nums));// 调用整数部分转换方法转换整数部分
} catch (Exception e) {
throw new IllegalArgumentException("For input string:" + in);
}
if (out.toString().equals("-0")) {
out.deleteCharAt(0);
}
return out.toString();
}
public static String figuresToWords(String in) {
/**
* 人民币小写转换大写
* @param 人民币小写数字
* @return 人民币大写数字
*/
String[] ch = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
StringBuilder out = new StringBuilder();// 定义返回值变量
StringBuilder integer = new StringBuilder(in);// 定义整数部分,假设传入参数为整数
if (in.endsWith("元")) {
integer.deleteCharAt(integer.length() - 1);// 删除末尾的“元”字
}
try {// 将所有异常统一设置为“传入参数错误”异常
if (integer.indexOf(".") != -1) {// 按“.”分割整数和小数部分
out.append(integer.substring(integer.indexOf(".") + 1));// 截取小数部分字符串
integer.delete(integer.indexOf("."), in.length());// 整数部分删除“.”及后面部分字符串
/**
* 分类转换小数部分
*/
switch (out.length()) {
case 1:// 一位小数
if (out.charAt(0) != '0') {
out.append(ch[out.charAt(0) - '0'] + '角');
}
out.deleteCharAt(0);
break;
case 2:// 两位小数
if (out.charAt(1) != '0') {
out.append(ch[out.charAt(1) - '0'] + '分');
}
out.deleteCharAt(1);
if (out.charAt(0) == '0') {
if (out.length() > 1) {
out.insert(1, '零');
}
} else {
out.insert(1, ch[out.charAt(0) - '0'] + '角');
}
out.deleteCharAt(0);
break;
default:// 超过两位小数则抛出“传入参数错误”异常
throw new Exception();
}
}
ch[0] = "";// 转换整数部分时“零”显示为空字符串
String integerOut = numToCh(integer, ch);// 转换整数部分
switch (integerOut) {// 分类合并整数与小数部分
case "零":// 整数为0时
if (out.length() == 0) {// 小数为0时
out.append("零元整");
} else if (out.charAt(0) == '零') {// 小数为0角X分时
out.deleteCharAt(0);
}
break;
case "负零":// 整数为-0时
if (out.length() == 0) {// 小数为0时
out.append("零元整");
} else {
if (out.charAt(0) == '零') {// 小数为0角X分时
out.deleteCharAt(0);
}
out.insert(0, '负');
}
break;
default:// 整数不为0时
if (out.length() == 0) {// 小数为0时
out.append(integerOut).append("元整");
} else {// 小数不为0时
out.insert(0, '元').insert(0, integerOut);
}
break;
}
} catch (Exception e) {
throw new IllegalArgumentException("For input string:" + in);
}
return out.toString();
}
public static String wordsToFigures(String in) {
/**
* 人民币大写转换小写
* @param 人民币大写数字
* @return 人民币小写数字
*/
Map<Character, Integer> nums = new HashMap<>();
nums.put('零', 0);
nums.put('壹', 1);
nums.put('贰', 2);
nums.put('叁', 3);
nums.put('肆', 4);
nums.put('伍', 5);
nums.put('陆', 6);
nums.put('柒', 7);
nums.put('捌', 8);
nums.put('玖', 9);
StringBuilder out = new StringBuilder();// 定义返回值变量
StringBuilder integer = new StringBuilder(in);// 定义整数部分,假设传入参数为整数
int decimalNum = 0;// 小数部分数值
if (in.endsWith("整") || in.endsWith("正")) {
integer.deleteCharAt(integer.length() - 1);// 删除末尾的“整”字
}
try {// 将所有异常统一设置为“传入参数错误”异常
String decimal = new String();// 定义小数部分字符串
if (integer.indexOf("元") != -1) {// 按“元”分割整数和小数部分
decimal = integer.substring(integer.indexOf("元") + 1);// 截取小数部分字符串
integer.delete(integer.indexOf("元"), integer.length());// 整数部分删除“元”及后面部分字符串
} else if (integer.indexOf("角") != -1 || integer.indexOf("分") != -1) {
if (integer.charAt(0) == '负' || integer.charAt(0) == '正') {// 带负不带负判断
decimal = integer.substring(1, integer.length());
integer.delete(1, integer.length());
} else {
decimal = integer.toString();
integer.delete(0, integer.length());
}
}
/**
* 分类转换小数部分
*/
switch (decimal.length()) {
case 0:// 整数类型不执行任何操作
break;
case 2:// X角或X分类型
if (decimal.charAt(1) == '角') {
decimalNum = nums.get(decimal.charAt(0)) * 10;
} else if (decimal.charAt(1) == '分') {
decimalNum = nums.get(decimal.charAt(0));
} else {
throw new Exception();
}
break;
case 3:// 零X分类型:
if (decimal.charAt(0) == '零') {
if (decimal.charAt(2) == '分') {
decimalNum = nums.get(decimal.charAt(1));
} else {
throw new Exception();
}
} else {
throw new Exception();
}
break;
case 4:// X角X分类型
if (decimal.charAt(1) == '角' && decimal.charAt(3) == '分') {
decimalNum = nums.get(decimal.charAt(0)) * 10 + nums.get(decimal.charAt(2));
} else {
throw new Exception();
}
break;
default:// 其余类型则抛出“输入参数错误”异常
throw new Exception();
}
out.append(chToNum(integer, nums));// 调用整数部分转换方法转换整数部分
if (decimalNum > 0) {
out.append('.').append(String.format("%02d", decimalNum));// 如果小数部分不为0则添加小数部分
}
out.append('元');
} catch (Exception e) {
throw new IllegalArgumentException("For input string:" + in);
}
return out.toString();
}
private static String numToCh(StringBuilder in, String[] ch) throws Exception {
/**
* 私有方法:阿拉伯整数数字转换汉语数字
* @param 阿拉伯整数数字,汉语数字1-9名称的数组
* @return 汉语数字
*/
StringBuilder out = new StringBuilder();// 定义返回值变量
if (in.indexOf("-") == 0 || in.indexOf("+") == 0) {// 正负数判断
// 如果有正负号则用递归方法先转换数字部分,再添加正负号
if (in.indexOf("-", 1) == -1 && in.indexOf("+", 1) == -1) {
char sign = in.charAt(0);
out.append(numToCh(in.deleteCharAt(0), ch));
if (sign == '-') {
out.insert(0, '负');
}
} else {
throw new Exception();
}
} else {// 转换整数部分
int n = 0;// 计算单位“亿”的个数
while (in.length() > 0) {
int index = in.length() > 8 ? in.length() - 8 : 0;
int intNum = Integer.parseInt(in.substring(index, in.length()));
if (intNum > 0) {
if (intNum % 10 == 0 && out.length() > 0) {
if (out.charAt(0) != '零') {
out.insert(0, '零');
}
}
for (int i = 0; i < n; i++) {
out.insert(0, '亿');
}
out.insert(0, numToCh(intNum, ch));
} else {
if (out.length() > 0 && out.charAt(0) != '零') {
out.insert(0, '零');
}
}
n++;
in.delete(index, in.length());
}
}
if (out.length() > 1) {
if (out.charAt(0) == '零') {
out.deleteCharAt(0);
}
} else if (out.length() == 0) {
out.append('零');
}
return out.toString();
}
private static String numToCh(int in, String[] ch) throws Exception {
/**
* 私有方法:亿以下阿拉伯整数数字转换汉语数字
* @param 亿以下数值型阿拉伯整数数字,汉语数字1-9名称的数组
* @return 汉语数字
*/
StringBuilder out = new StringBuilder();
if (in < 10000) {// 万以下数字转换
if (!ch[1].equals("壹") && in < 20 && in >= 10) {
out.append('十').append(ch[in % 10]);
} else {
char[] num = String.valueOf(in).toCharArray();
String[] units = { "", "十", "百", "千" };
if (ch[1].equals("壹")) {
units[1] = "拾";
units[2] = "佰";
units[3] = "仟";
}
for (int i = 0; i < num.length; i++) {
if (num[num.length - i - 1] == '0') {
if (!(out.length() == 0 || out.charAt(0) == '零')) {
out.insert(0, '零');
}
} else {
out.insert(0, units[i]);
out.insert(0, ch[(int) num[num.length - i - 1] - (int) '0']);
}
}
}
} else {// 万以上数字转换
out.append(numToCh(in % 10000, ch));
if (out.length() > 0 && (in % 10000 < 1000 || in / 10000 % 10 == 0)) {
out.insert(0, '零');
}
out.insert(0, '万');
out.insert(0, numToCh(in / 10000, ch));
}
return out.toString();
}
private static String chToNum(StringBuilder in, Map<Character, Integer> nums) throws Exception {
/**
* 私有方法:汉语整数数字转换阿拉伯数字
* @param 汉语整数数字,1-9汉语和阿拉伯数字名称对照表集合
* @return 阿拉伯整数数字
*/
StringBuilder out = new StringBuilder();
if (in.indexOf("负") == 0 || in.indexOf("正") == 0) {// 正负数判断
// 如果有正负号则用递归方法先转换数字部分,再添加正负号
if (in.indexOf("负", 1) == -1 && in.indexOf("正", 1) == -1) {
char sign = in.charAt(0);
out.append(chToNum(in.deleteCharAt(0), nums));
if (sign == '负') {
out.insert(0, '-');
}
} else {
throw new Exception();
}
} else {// 转换数字部分
for (int i = 0; i < in.length(); i++) {
if (in.charAt(i) == '零' && i != in.length() - 1) {
in.deleteCharAt(i);// 去掉所有前缀“零”
i--;
} else if ((in.charAt(i) == '十') && (i == 0 || !nums.containsKey(in.charAt(i - 1)))) {
in.insert(i, '一');// 将“十”改为“一十”
i++;
} else if ((in.charAt(i) == '拾') && (i == 0 || !nums.containsKey(in.charAt(i - 1)))) {
in.insert(i, '壹');// 将“拾”改为“壹拾”
i++;
}
}
while (in.length() > 0) {// 从右到左以“亿”为界分段转换
int n = 0;// 统计字符串尾部“亿”的个数
while (in.charAt(in.length() - 1) == '亿') {
n++;
in.deleteCharAt(in.length() - 1);
}
while (out.length() < n * 8) {// 按“亿”的个数补足位数
out.insert(0, '0');
}
int index = in.lastIndexOf("亿");
out.insert(0, chToNum(in.substring(index + 1), nums));
in.delete(index + 1, in.length());
}
}
if (out.length() == 0) {
out.append('0');// 转换数字为空则转换为“零”
}
return out.toString();
}
private static int chToNum(String in, Map<Character, Integer> num) throws Exception {
/**
* 私有方法:亿以下汉语整数数字转换阿拉伯数字
* @param 亿以下汉语整数数字,1-9汉语和阿拉伯数字名称对照表集合
* @return 数值型阿拉伯整数数字
*/
if (in.indexOf("万") != -1) {// 万以上数字转换
String left = in.substring(0, in.indexOf("万"));
String right = in.substring(in.indexOf("万") + 1);
if ((right.indexOf("万") == -1)) {
return chToNum(left, num) * 10000 + chToNum(right, num);
} else {
throw new Exception();
}
} else {// 万以下数字转换
Map<Character, Integer> units = new HashMap<>();
units.put('十', 10);
units.put('拾', 10);
units.put('百', 100);
units.put('佰', 100);
units.put('千', 1000);
units.put('仟', 1000);
int out = 0;// 定义返回值变量
int unit = 1;// 单位
for (int i = in.length() - 1; i >= 0; i--) {
if (num.containsKey(in.charAt(i))) {
out += num.get(in.charAt(i)) * unit;
} else {
unit = units.get(in.charAt(i));
}
}
return out;
}
}
}