版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhaohuiyang_949/article/details/80204415
侵删!
在《疯狂JAVA讲义》第4章最后练习题中,第5题:编写一个程序,将浮点数转换成人民币读法字符串,例如,将1006.33转换成一千零六元三角三分。
这个题主要是一个逻辑判断的过程。首先考虑的问题是整数部分和小数部分,我们在这里给小数部分做个限制,因为只有角和分,所以就固定判断小数部分只有两位数。小数部分就分别判断角和分。接下来是整数部分,由于考虑到整数部分可能过长,所以我们在处理的时候,将整数部分分割成4个数为一部分,一部分一部分的来处理。每一个部分都是4位数,就分别判断千,百,十。在判断的过程中,要注意“零”问题的处理,比如:1003。这个是我参考的原文章:java实战1——浮点数转人民币读法。
以下是完整的代码,代码中有详细的注释:
import java.util.Scanner;
public class FloatToChinese {
//汉字数组
private String[] chineseArr = new String[]{"零","一","二","三","四","五","六","七","八","九"};
//单位数组
private String[] unitArr = new String[]{"千","百","十"};
public static void main(String[] args) {
// write your code here
FloatToChinese floatToChinese = new FloatToChinese();
Scanner console = new Scanner(System.in);
//保存输入的数值
double num = 0.0;
num = console.nextDouble();
String result = floatToChinese.numStrToChineseStr(num);
System.out.println(result);
}
/**
* 四位数的字符串转人民币读法
* 如果输入numStr 不够4位就前补零,变为4位
* @param numStr 将整个数字字符串分割成每4位数一组后的,数字字符串
* @return 当前4位数字转换成人民币读法后的,汉字字符串
*/
public String numStrToChineseStrIntPartCore(String numStr) {
String result = ""; //保存结果,初始化为空
int len = numStr.length(); //获取numStr的长度
//补零操作
if(len < 4) //位数小于4位就在前面补零
{
String[] addZeroStr = {"0","00","000"};
//4减去长度等于需要补零的个数,要补充的0在addZeroStr中,需要使用数组下标,所以再减一
numStr = addZeroStr[4-len-1] + numStr;
}
len = numStr.length(); //更新长度,len==4
//扫描至第一个不为0的字符
int i=0;
//i表示下标,下标小于长度,并且截取字符串的每一个字符和“0”比较
while(i < len && numStr.charAt(i)-'0'==0){
i++;
}
//如果4个数都是0,那么直接输出一个0,并返回结果。
if(i==len){
result += "零";
return result;
}
//四个数不都为0的情况,扫描4个数
for(;i < len; i++){
//使用单引号时表示char,使用双引号时,表示String
//charAt()返回的是一个char类型的值,char类型的值,可以直接相减(自动转换成ASCLL码值相减)
//获取的单个字符,和0的ASCLL码值相差多少,数值就是多少。
int num = numStr.charAt(i) - '0';
//不是末尾且不为0
if( i != len-1 && num != 0){
//直接映射汉字和单位,num汉字的下标,i单位的下标
result += chineseArr[num] + unitArr[i] ;
} else {
//若当前结果字符串中最后一位不是“零”,且数字串最后一位不是数字0 这样对中间2个零的只添加一个“零”如1003
if( result.length()>0 && result.charAt(result.length()-1) != '零'
&& numStr.charAt(len-1)-'0'!= 0) {
//四位中第二,三位至少有一个为0且最后一位数字不为0 如1003 则为一千零三
if((i==1||i==2) && num == 0){
result += "零";
}
}
//是最后一位,且数字不为0 不加单位
if( i == len - 1 && num != 0) {
result += chineseArr[num];
}
}
}
return result; //返回结果字符串
}
/**
* 获取数字字符串有效位
* 从第一位开始,不为0的数
* @param str 整个数字字符串
* @return 返回第一个不为0的数字的位置
*/
public int getValidStrLen(String str) {
//起始位置
int start = 0;
//当前数字字符串长度
int len = str.length();
//从第一个开始遍历,如果为0,就检查下一个,不为0就找到第一个有效数字
while(start < len && str.charAt(start) =='0'){
start++ ;
}
//start++,表示了当前无效位的个数,计算的时候分成4个数字一组
return 4 - start;
}
/**
* 将12位整数部分数字转为汉字字符串
* @param numStr 整个数字字符串
* @return 整个数字字符串转换为人民币读法后的汉字字符串
*/
public String numStrToChineseStrIntPart(String numStr) {
//获取整个数字字符串的总长度
int len = numStr.length();
//判断输入的数字字符串分成4位1组,能分成几份
int partNum = (len%4==0) ? (len/4) : (len/4)+1;
//分别定义亿,万,元单位字符串
String strYi="",strWan="",strYuan="";
//12位以内的数字字符串最多能分成三部分
String firstStr,secondStr,thirdStr;
//用于保存分割成4位后的数字字符串有效字符串长度,去除0
int tempLen;
boolean fourValidBitYuan = false ; //判断第三部分是否为4位
switch(partNum) {
//只有1部分,就是xxx元
case 1:
//如果只有1部分,就不用分割,直接转换
strYuan += numStrToChineseStrIntPartCore(numStr);
break;
//有2部分,就是 xxx万xxx元
case 2:
//注意 String.substring(beginindex,endIndex)中endindex不包含
int endIndex = len - 4 ;
//一部分一部分的截取
firstStr = numStr.substring(0,endIndex);
strWan += numStrToChineseStrIntPartCore(firstStr)+"万";
secondStr = numStr.substring(endIndex,len);
strYuan += numStrToChineseStrIntPartCore(secondStr);
tempLen = getValidStrLen(secondStr);
if(0 <tempLen && tempLen < 4 ){
strYuan = "零"+ strYuan;
}
break;
//有3部分,就是 xxx亿xxx万xxx元
case 3:
int endIndex2 = len - 4;
int endIndex1 = endIndex2 - 4;
firstStr = numStr.substring(0,endIndex1);
strYi += numStrToChineseStrIntPartCore(firstStr)+"亿";
secondStr = numStr.substring(endIndex1,endIndex2);
strWan += numStrToChineseStrIntPartCore(secondStr)+"万";
tempLen = getValidStrLen(secondStr);
//中间过程进行补零
if(0< tempLen && tempLen<4 ) {
strWan = "零"+strWan;
}
thirdStr = numStr.substring(endIndex2,len);
strYuan += numStrToChineseStrIntPartCore(thirdStr) ;
tempLen = getValidStrLen(thirdStr);
if(0 <tempLen && tempLen < 4 ){
strYuan = "零"+ strYuan;
} else {
if( tempLen == 4)
fourValidBitYuan = true;
}
break;
default:
break;
}
//对结果进行判断,如果万位和元位都为0
if(strWan.equals("零万")) {
//Str_wan为"零万"且元部分为4位。如12300001234中间需读出"零"
if(fourValidBitYuan ){
strWan = "零";
}
//否则就不添加
else{
strWan = "";
}
}
if( strYuan.equals("零")){
strYuan = "";
}
return strYi + strWan + strYuan + "元";
}
/**
* 处理小数部分字符串,小数部分最多两位
* @param floatStr 小数部分字符串
* @return 返回小数部分转换成人民币读法的汉字字符串
*/
public String numStrToChineseStrFloatPart(String floatStr) {
String resultJiao = "",resultFen = "";
//小数部分长度
int len = floatStr.length();
//补零操作,位数小于两位,就在前面补0
if(len < 2) {
//和整数部分补位,同理
String[] addZeroStr = {"0","00"};
floatStr = addZeroStr[2-len-1] + floatStr;
}
//固定的两位,角和分
for(int i=0 ; i < 2 ; ++i) {
//获取当前的数值
int num = floatStr.charAt(i) - '0';
//当是小数部分第一位的时候
if( i == 0) {
//映射数值
resultJiao += chineseArr[num] ;
//如果不等于0,添加单位
if( num != 0){
resultJiao += "角";
}
}
//当是小数部分第二位的时候
else {
//判断不为0,映射数值,并添加单位
if(num !=0){
resultFen += chineseArr[num]+"分";
}
}
}
//检查一次,当小数部分两个数都为0的时候
if( resultFen.equals("") && (resultJiao.equals("零")||resultJiao.equals("零角"))){
resultJiao = "";
}
return resultJiao + resultFen;
}
/**
* 将一个有效位为15以内的浮点数转换成人民币读法
* @param num 将要转换的浮点数
* @return 返回转换成人民币读法后的汉字字符串
*/
public String numStrToChineseStr(double num) {
//将浮点数直接强转成长整型
long intPart = (long)num;
//因为强转的时候,会造成精度丢失,使用Math.round进行四舍五入
//浮点数减去整数部分等于小数部分,再*100,就等到小数部分的两个数值
long floatPart = Math.round((num - intPart)*100);
//将intPart和floatPart前面加个空字符串,将long型转换成字符串
return numStrToChineseStrIntPart("" + intPart) + numStrToChineseStrFloatPart(""+floatPart);
}
}
运行效果如图:
整个代码,最关键的就是处理整数部分的逻辑问题,只要把这个逻辑关系捋清楚了就行。如果发现有问题,请指出,谢谢。