编写一个程序,将浮点数转换成人民币读法字符串,例如,将1006.333转换成壹千零陆元叁角叁分。
参考已有的解决方案上进一步完善,在1000亿范围内基本符合人民币金额读写规范。
特殊情况解决:
- 输入的数为0直接输出“零元整”
- 小数位只有分位且整数位不为零时分位前应加“零”,例如,12.04应转换成“壹拾贰元零肆分”
- 小数位为零且整数位不为零时应在整数位后加“整”,例如,12应转换成“壹拾贰元整”
- 分组转换时,如果分成3组,若中间一组全是零,会只保留一个零,又因为最低位为零而被删除,进而这一组返回值为空,但这里又需要一个零,例如,100001234应转换成“壹亿零壹仟贰佰叁拾肆元整”,而不是“壹亿壹仟贰佰叁拾肆元整”
- 解决上一个问题后,1亿的转换结果会多一个零:壹亿零元整。设置条件如果中间一组全是零且上一组也全是零,删除这个零
- 解决上两个问题后,100000001(一亿零一):第一组“0001”会保留一个零,而第二组“0000”不满足上一个特殊情况的条件,依然会保留一个零,就会转换成“壹亿零零壹佰元整”,删除多余的零
public class Num2Rmb {
private final String[] hanArr = {"零" , "壹" , "贰" , "叁" , "肆" ,
"伍" , "陆" , "柒" , "捌" , "玖"};
private final String[] unitArr = {"拾" , "佰" , "仟"};
private final String[] uArr = {"元" , "万" , "亿"};
// 把浮点数分解成整数部分字符串
private String divideZheng(double num) {
long zheng = (long) num;
return zheng + "";
}
// 把浮点数分解成小数部分字符串
private String divideXiao(double num) {
long xiao = Math.round((num - (long) num) * 100);
return String.valueOf(xiao);
}
// 把一个小于等于四位的数字字符串变成汉字字符串
private String zhengToStr(String numStr) {
int numLength = numStr.length(); // 字符串长度
int resultLength = 0; // 转换结果长度
String result = "";
// 依次遍历数字字符串的每一位数字
for (int i = 0; i < numLength; i++) {
// 将char型数字转换成int型数字
int num = numStr.charAt(i) - 48;
// 如果不是最后一位数字,且数字不是零,则需添加单位(拾,佰,仟)
if (i != (numLength - 1) && num != 0)
result += hanArr[num] + unitArr[numLength - 2 - i];
// 如果第一位为零,直接转换
else if (i == 0 && num == 0)
result += hanArr[num];
// 如果多个零连在一起,只保留一个零
else if (!(num == 0 && result.charAt(resultLength - 1) == '零'))
result += hanArr[num];
// 长度随着转换进度而变化
resultLength = result.length();
}
// 最低位是零,删除最低位
if (result.charAt(resultLength - 1) == '零') {
result = result.substring(0, resultLength - 1);
}
return result;
}
// 把小数部分数字字符串变成汉字字符串
private String xiaoToStr(String numStr) {
// 小数部分有两位
if (numStr.length() == 2) {
int jiao = numStr.charAt(0) - 48;
int fen = numStr.charAt(1) - 48;
if (fen != 0) return hanArr[jiao] + "角" + hanArr[fen] + "分";
// 小数第二位(分)为0
else return hanArr[jiao] + "角";
}
// 小数部分只有一位且不为零
else if (numStr.length() == 1 && !numStr.equals("0")) {
int fen = Integer.parseInt(numStr);
return hanArr[fen] + "分";
}
// 小数部分为零
else return "整";
}
// 将整数部分字符串按四位为一组,分组转换成汉字字符串,不足四位的单独转换
private String zhengDivide(String numStr) {
int numLength = numStr.length(); // 整数位长度
// 整数位过长
if (numLength > 11) {
return "too large";
}
// 整数位为零
if (numLength == 1 && numStr.charAt(0) == '0')
return "";
// 分为几组
int arr = (numLength - 1) / 4 + 1;
String result = ""; // 存放转换结果
String temp; // 中间变量,临时存放
String zheng; // 存放要拿去转换的数字字符串
// 满四位的有几组进行几次循环
for (int i = 1; i < arr; i++) {
numLength = numStr.length();
zheng = numStr.substring(numLength - 4);
numStr = numStr.substring(0, numLength - 4);
// 对特殊情况中间一组全是零,如100002894
if (i != 1 && allZero(zheng)) {
temp = "零" + result;
}
// 正常情况
else {
temp = zhengToStr(zheng);
temp += uArr[i - 1] + result;
}
result = temp;
}
// 不足四位的单独转换
temp = zhengToStr(numStr);
temp += uArr[arr - 1] + result;
result = temp;
// 特殊情况1亿转换结果为“壹亿零元整”,删除“零”
if (result.charAt(result.length() - 2) == '零') {
result = result.substring(0, result.length() - 2) +
result.substring(result.length() - 1);
}
// 特殊情况万位和千位都为零会出现连续两个零
// 如100000100的转换结果为“一亿零零壹佰元整”,删除多余的零
for (int j = 0; j < result.length(); j++) {
if (result.charAt(j) == '零' && result.charAt(j + 1) == '零') {
result = result.substring(0, j) + result.substring(j + 1);
break;
}
}
return result;
}
// 判断zhengDivide方法中变量zheng是否全为零
private boolean allZero(String zheng) {
boolean a = true;
for (int i = 0; i < 4; i++) {
if (zheng.charAt(i) != '0') {
a = false;
break;
}
}
return a;
}
public static void main(String[] args) {
Num2Rmb nr = new Num2Rmb();
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
double num = sc.nextDouble();
String zheng = nr.zhengDivide(nr.divideZheng(num));
String xiao = nr.xiaoToStr(nr.divideXiao(num));
// 判断输入的浮点数是否为零
if (Math.round(num * 100) == 0)
System.out.println("零元整");
// 整数位过长
else if (zheng.equals("too large"))
System.out.println("金额过大,应小于1000亿元!");
// 如果整数位不为零且小数位只有分,在整数位和小数位之间加“零”
else if (!zheng.equals("") &&
xiao.length() == 2 && xiao.charAt(1) == '分')
System.out.println(zheng + "零" + xiao);
else
System.out.println(zheng + xiao);
}
}
}
测试结果:
出于一种执着,写出了我能想到的最完善的方案,但依然有待改进完善,欢迎批评指正,交流讨论,给出更好的方法