数字的英文表达和中文表达

题目

给定一个32位的整数num,写两个函数分别返回它的英文表达和中文表达字符串.
然后我们来看看几个例子.


图片.png

笔者已经将最复杂的数字进行了分析,这个值是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的话就会溢出,结果运行结果如下:


图片.png

所以这就是我们要对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++;
}

然后就是中文的表达

图片.png

我们注意到中文时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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343