题目
给定一个32位的整数num,写两个函数分别返回它的英文表达和中文表达字符串.
然后我们来看看几个例子.
笔者已经将最复杂的数字进行了分析,这个值是Integer.MIN_VALUE,如图Two Billion,One Hundred Forty Seven Million,.......Thousand,Six Hundred Forty Eight.我们注意到其中基本都是1---999的数字然后在加上Million,Thousand这些单位,这样的话,我们的首要目的就是找出1---999的数字表达.
1---19的英文表达
我们可以通过枚举的方式,将所有19个可能性放入到一个String数组中去,十分简单,如下图:
public static String num1To19(int num)
{
if(num<1||num>19)
{
return "";
}
String[] names={"One ","Two ","Three ","Four ","Five ","Six ","Seven ","Eight ","Nine ",
"Ten ","Eleven ","Twelve ","Thirteen ","Fourteen ","Fifteen ","Sixteen ","Seventeen ",
"Eightteen ","Nineteen "
};
return names[num-1];
}
当我们传入16是,就找出这个数组中16-1,下标为15的表达.十分简单,现在完成了1---19的表达,然后我们来完成1---99的表达,我们通过/运算得到十位,用一个数组来承担,然后通过%运算得到低位,然后使用num1to19来表达
public static String num1To99(int num)
{
if(num<1||num>99)
{
return "";
}
if(num<20)
{
return num1To19(num);
}
int high=num/10;
String[] tyNames={"Twenty ","Thirty ","Forty ","Fifty ","Sixty ","Seventy ","Eighty "
,"Ninety "};
return tyNames[high-2]+num1To19(num%10);
}
依次类推,我们现在知道了1---99的表达,然后我们通过/和%运算就可以得到1---999的表达了,但是要注意,在中间加上,"Hundred".
//1---999
public static String num1To999(int num)
{
if(num<1||num>999)
{
return "";
}
if(num<100)
{
return num1To99(num);
}
int high=num/100;
return num1To19(high)+"hundred "+num1To99(num%100);
}
然后就是主函数了.
我们先把代码贴上来,然后再去分析为什么这样写
public static String getNumEngExp(int num)
{
if(num==0)
{
return "Zero";
}
String res="";
if(num<0)
{
res="Negative, ";
}
if(num==Integer.MIN_VALUE)
{
res+="Two Billion,";
num%=-2000000000;
}
num=Math.abs(num);//求绝对值
int high=1000000000;
int highIndex=0;
String[] names={"Billion","Million","Thousand",""};
while(num!=0)
{
int cur=num/high;
System.out.println(cur);
num%=high;
if(cur!=0)
{
res+=num1To999(cur);
res+=names[highIndex]+(num==0?" ":", ");
}
high/=1000;
highIndex++;
}
return res;
}
- 第一步判断num是不是0,如果是0的话直接返回num
- 第二步判断是不是负数,如果num<0,我们家在操作之前加上negative,
- 重点来了,我们这儿为什么要将Integer.MIN_VALUE单另的拿出来做判断.
因为如果不做处理的话,将Integer.MIN_VALUE转化成整数的话,就会溢出,我们举个例子.
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
就是简单了两句代码,我们知道MAX_VALUE指的是32位有符号正整数的最大位置,如果这个位置加1的话就会溢出,结果运行结果如下:
所以这就是我们要对Integer.MIN_VALUE进行单独处理的原因.
先得到他的最高位,然后取模,得到他除了最高位的数,然后进行循环.
- 然后就是循环了,我们再把循环贴出来
while(num!=0)
{
int cur=num/high;//1000000000
System.out.println(cur);
num%=high;
if(cur!=0)
{
res+=num1To999(cur);
res+=names[highIndex]+(num==0?" ":", ");
}
high/=1000;
highIndex++;
}
return res;
我们以Integer.MAX_VALUE为例,第一次遍历得到的cur为2,然后得到它的次高位等待.每次都要选出三位来,如果我们每次要选出一位出来,那就/10,如果一次要选出两位出来那就/100,所以这里我们要/1000,每次/1000,就可以选出3位,同时最开始的high的设值,0的个数一定是3的倍数,这道题就是9个零.
同时我们要注意/和%的协作运算.加深印象,我们在这道题中,在重新写一下
num=Math.abs(num);
int high=1000000000;
while(num!=0)
{
cur=num/high;
num=num%high;
if(cur!=0)
{
res+=num1To999(cur);
加上位数
}
high/=1000;
highIndex++;
}
然后就是中文的表达
我们注意到中文时4位为一次重复,然后修改其后面的单位即可.
直接贴代码了
public static String num1To9(int num)
{
if(num<1||num>9)
{
return "";
}
String[] names={"一","二","三","四","五","六","七","八","九"};
return names[num-1];
}
public static String num1To99(int num,boolean hasBai)
{
if(num<1||num>99)
{
return "";
}
if(num<10)
{
return num1To9(num);
}
//得到高位
int shi=num/10;
if(shi==1&&(!hasBai))//如果有百位的情况 三百一十九
{
return "十"+num1To9(num%10);
}else
{
return num1To9(shi)+"十"+num1To9(num%10);
}
}
public static String num1To999(int num)
{
if(num<1||num>999)
{
return "";
}
if(num<100)
{
return num1To99(num,false);
}
String res=num1To9(num/100)+"百";
int rest=num%100;
if(rest==0)
{
return res;
}else if(rest>=10)
{
res+=num1To99(rest,true);
}else
{
res+="零"+num1To9(rest);
}
return res;
}
public static String num1To9999(int num)
{
if(num<1||num>9999)
{
return "";
}
if(num<1000)
{
return num1To999(num);
}
String res=num1To9(num/1000)+"千";
int rest=num%1000;
if(rest==0)
{
return res;
}else if(rest>=100)
{
res+=num1To999(rest);
}else
{
res+="零"+num1To99(rest, false);
}
return res;
}
public static String num1To99999999(int num)
{
if(num<1||num>99999999)
{
return "";
}
int wan=num/10000;
int rest=num%10000;
if(wan==0)
{
return num1To9999(rest);
}
String res=num1To9999(wan)+"万";
if(rest==0)
{
return res;
}else
{
if(rest<1000)
{
return res+"零"+num1To999(rest);
}else
{
return res+num1To9999(rest);
}
}
}
public static String getNumChiExp(int num)
{
if(num==0)
{
return "零";
}
String res=num<0?"负":"";
int yi=Math.abs(num/100000000);
int rest=Math.abs(num%100000000);
if(yi==0)
{
return res+num1To99999999(rest);
}
res+=num1To9999(yi)+"亿";
if(rest==0)
{
return res;
}else
{
if (rest < 10000000) {
return res + "零" + num1To99999999(rest);
} else {
return res + num1To99999999(rest);
}
}
}
public static String getNumChiExp2(int num)
{
if(num==0)
{
return "零";
}
String res=num<0?"负":"";
int high=100000000;
int highIndex=0;
if(num==Integer.MIN_VALUE)
{
res+=num1To9999(num/high*-1)+"亿";
num=num%high;
highIndex++;
}
num=Math.abs(num);
String[] names={"亿","万",""};
while(num!=0)
{
int cur=num/high;
num=num%high;
if(cur!=0)
{
res+=num1To9999(cur)+names[highIndex];
}
high/=10000;
highIndex++;
}
return res;
}
public static void main(String[] args) {
System.out.println(getNumChiExp2(323232));
System.out.println(getNumChiExp(323232));
}
最后还有几句想说的,关于/和%的配合使用问题,如果想获得当前的位,那么就是用一个10000.....(总位数等于被除数),这是做/运算,如果是做%运算,上面的情况就是获取除当前位的其他位数.
然后就是Integer.MAX_VALUE和Integer.MIN_VALUE,当处理比较大的数据时,就要考虑到溢出的情况,同时MAX_VALUE比MIN_VALUE的绝对值小1.