从一读到一亿需要读多少个汉字?

从一读到一亿需要读多少个汉字?

题目分析

  首先对读法做一下规范,我是做过两年审计工作,所以习惯于采用会计的大写方式
  例如(没有测试所有格式,仅测试了如下个别代表性数据;这里的十均表示为"壹拾",间隔有零均读零):

数据大写数据大写数据大写
110,100壹萬零壹佰110,110壹拾壹萬零壹佰壹拾
10壹拾11,000壹萬壹仟111,001壹拾壹萬壹仟零壹
100壹佰11,100壹萬壹仟壹佰1,000,000壹佰萬
101壹佰零壹11,010壹萬壹仟零壹拾1,001,000壹佰萬零壹仟
110壹佰壹拾10,110壹萬零壹佰壹拾1,100,101壹佰壹拾萬零壹佰零壹
111壹佰壹拾壹111,011壹拾壹萬壹仟零壹拾壹1,100,101壹佰壹拾萬零壹佰零壹
1,000壹仟110,111壹拾壹萬零壹佰壹拾壹1,101,100壹佰壹拾萬零壹仟壹佰
1,001壹仟零壹101,111壹拾萬零壹仟壹佰壹拾壹1,110,100壹佰壹拾壹萬零壹佰
1,010壹仟零壹拾100,010壹拾萬零壹拾1,111,000壹佰壹拾壹萬壹仟
1,100壹仟壹佰100,100壹拾萬零壹佰10,010,000壹仟零壹萬
1,011壹仟零壹拾壹101,000壹拾萬零壹仟10,100,001壹仟零壹拾萬零壹
1,110壹仟壹佰壹拾110,000壹拾壹萬11,000,000壹仟壹佰萬
1,101壹仟壹佰零壹100,011壹拾萬零壹拾壹10,010,001壹仟零壹萬零壹
1,111壹仟壹佰壹拾壹100,101壹拾萬零壹佰零壹10,011,001壹仟零壹萬壹仟零壹
10,100壹萬零壹佰101,001壹拾萬壹仟零壹10,010,100壹仟零壹萬零壹佰

思路分析

  本来想采用列举的方式一个一个写出来,就像下面这样:

public static void main(String[] args) {
        int count = 0;
        int plus;
        //此处计算的是1-10,因为这些数字每个都是一个汉字;
        for (int i = 1; i <= 10; i++) {
            count += 1;
        }
        //此处计算的是11-20,因为这些数字每个都是两个汉字;
        for (int i = 11; i <= 20; i++) {
            count += 3;
        }
        //此处计算的是21-99,因为这些数字只要能被十整除,均是两个汉字(例如:二十,三十);只要不能被十整除,均是三个汉字(例如:二十三,四十七,九十九);
        //这是还比较简单,不需要调用找零的个数方法;
        for (int i = 21; i <= 99; i++) {
            plus = i % 10 == 0 ? 2 : 3;
            count += plus;
        }
        //此处计算的是100-999,此项比较麻烦,总体分为三种:
        // 两个汉字(例如:三百,四百),他们的特点是整百整千,能够被100整除;
        // 四个汉字(例如:二百零七,三百一十),他们的特点是含零,且只有一个零,种类较多,可以先看五个汉字的,然后剩下的都是四个汉字;
        // 五个汉字(一百二十三,九百九十九),他们的特点是不含零;
        for (int i = 100; i <= 999; i++) {
            if (i % 100 == 0) {
                plus = 2;
            } else if (findZero(i) == 0) {
                plus = 5;
            } else {
                plus = 4;
            }
            count += plus;
        }
        //此处计算的是1000-9999,从此处就开始往下麻烦,总体分为五种:
        // 两个汉字(例如:两千,五千),他们的特点是整千整万,能够被1000整除;
        // 四个汉字(例如:三千零一,一千一百,三千二百),他们的特点是去掉个位,可以被10整除,并且自己不能被十整除(例如:一千一百零一虽然满足去个位可被十整除,但是它有五位);
        // 五个汉字(例如:一千零一十),他们的特点是,在前两者判断完成的前提下,自己能够被10整除,并且去掉两位也可以被10整除;
        // 六个汉字(例如:一千七百三十,九千一百零一,一千零五十二),种类较多,可以先看七个汉字的,然后剩下的都是六个汉字;
        // 七个汉字(例如:一千三百五十七),他的特点是,不含零,可以调用findZero的方法来进行计数;
        for (int i = 1000; i <= 9999; i++) {
            //此处括号里的(i % 1000 == 0)判定条件也可以替换为(findZero(i) == 3)
            if (i % 1000 == 0) {
                plus = 2;
            } else if ((i % 10 != 0) && i / 10 % 10 == 0) {
                plus = 4;
            } else if ((i % 10 == 0) && i / 100 % 10 == 0) {
                plus = 5;
            } else if (findZero(i) == 0) {
                plus = 7;
            } else {
                plus = 6;
            }
            count += plus;
        }
        System.out.println(count);
    }

  就像上面一样,直接卡在了一万以下,况且无法对随意数据进行取值,所以采用了另一种方法:即先进行大写转换,然后利用统计转换后的大写读法字符的长度来进行统计.

方法改进

具体思路

  首先,最重要的是创建一种方法来把读法完成,即两种:一种是阿拉伯直接转换的数字(7→柒,0→零),另一种是位数(个十百千万,其中个不用读),所以先创建两个数组(下图为改进过的,万比较特殊,万前和万后读法相近,可以调用方法,所以把万字单独列出来)

        char[] num = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
        char[] digit = {'拾', '佰', '仟'};
        char[] digitHuge = {'萬'};

  先创建方法来对两种读法进行分割:
  下面代码的方法是对数字进行转化:

private static String getBigNumber(int numberR) {
        int number = numberR;
        char[] num = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
        String sNumber = String.valueOf(number);
        char[] arr = sNumber.toCharArray();
        char[] arr2 = new char[arr.length];
        for (int i = 0; i < arr.length; i++) {
            arr2[i] = num[Integer.parseInt(String.valueOf(arr[i]))];
        }
        StringBuffer str = new StringBuffer();
        for (char s : arr2) {
            str.append(s);
        }
        String numberBig = str.toString();
        return numberBig;
    }

下面代码的方法是对"位"进行转化:

private static String getDigit(int numberR) {
        int number = numberR;
        char[] digit = {'拾', '佰', '仟'};
        String sNumber = String.valueOf(number);
        char[] arr = sNumber.toCharArray();
        char[] arr2 = new char[arr.length - 1];
        for (int i = 0; i < arr.length - 1; i++) {
            arr2[i] = digit[i];
        }
        StringBuffer str = new StringBuffer();
        for (char s : arr2) {
            str.append(s);
        }
        String digitDo = str.toString();
        return digitDo;
    }

  然后就采用穿法取元素的方法进行拼接(比如三千五百零拾六–之后会对读法进行优化,现在先进行简单的拼接):

private static String nameChinese(int n) {
        String bigNumber = getBigNumber(n);
        char[] nnn = bigNumber.toCharArray();
        String digit = getDigit(n);
        char[] ddd = digit.toCharArray();
        String sA = String.valueOf(n);
        char[] arrA = sA.toCharArray();
        char[] arr2 = new char[arrA.length * 2 - 1];
        for (int i = 0; i < arrA.length * 2 - 1; i++) {
            if (i % 2 == 0) {
                arr2[i] = nnn[i / 2];
            } else {
                arr2[i] = ddd[ddd.length - i / 2 - 1];
            }
        }
        StringBuffer str = new StringBuffer();
        for (char s : arr2) {
            str.append(s);
        }
        String s = str.toString().replace("零佰零拾", "零").replace("零佰", "零").replace("零拾", "零");
        String noTailNumber;
        if (n == 0) {
            noTailNumber = "";
        } else if (n % 100 == 0 && n >= 100) {
            noTailNumber = s.substring(0, s.length() - 2);
        } else if (n % 10 == 0 && n % 100 != 0 && n >= 10) {
            noTailNumber = s.substring(0, s.length() - 1);
        } else {
            noTailNumber = s;
        }
        return noTailNumber;
    }

  这段代码中的

.replace(“零佰零拾”, “零”).replace(“零佰”, “零”).replace(“零拾”, “零”)

  这一部分,本来是在此方法之后的取零步骤进行操作的,可是遇到了一些问题(末尾有零,其他位数后转换效果不好等情况),结果现在去不掉了,所以依旧留着.

  拼接完成之后就是拼接"万"类的前后字符串:

private static String nameWanChinese(int n) {
        String sN = String.valueOf(n);
        char[] arrN = sN.toCharArray();
        char[] arrStart = new char[arrN.length - 4];
        char[] arrEnd = new char[4];
        System.arraycopy(arrN, 0, arrStart, 0, arrN.length - 4);
        System.arraycopy(arrN, arrN.length - 4, arrEnd, 0, 4);
        StringBuffer strStart = new StringBuffer();
        for (char s : arrStart) {
            strStart.append(s);
        }
        String start = strStart.toString();
        StringBuffer strEnd = new StringBuffer();
        for (char s : arrEnd) {
            strEnd.append(s);
        }
        String end = strEnd.toString();
        if ((Integer.parseInt(end) < 1000 && Integer.parseInt(end) > 0) || (Integer.parseInt(start) % 10 == 0 && Integer.parseInt(start) >= 10&&Integer.parseInt(end)!=0)|| (Integer.parseInt(start) % 100 == 0 && Integer.parseInt(start) >= 100&&Integer.parseInt(end)!=0)|| (Integer.parseInt(start) % 1000 == 0 && Integer.parseInt(start) >= 1000&&Integer.parseInt(end)!=0)) {
            return (nameChinese(Integer.parseInt(start)) + "萬零" + nameChinese(Integer.parseInt(end)));
        } else {
            return (nameChinese(Integer.parseInt(start)) + "萬" + nameChinese(Integer.parseInt(end)));
        }
    }

  这里面最长的那一串是if ((Integer.parseInt(end) < 1000 && Integer.parseInt(end) > 0) || (Integer.parseInt(start) % 10 == 0 && Integer.parseInt(start) >= 10&&Integer.parseInt(end)!=0)|| (Integer.parseInt(start) % 100 == 0 && Integer.parseInt(start) >= 100&&Integer.parseInt(end)!=0)|| (Integer.parseInt(start) % 1000 == 0 && Integer.parseInt(start) >= 1000&&Integer.parseInt(end)!=0)),这段代码是为了让100,000,101,000,这类的数字准确输出读法,否则会出现"十万零"或者"十万一千"这样的错误读法.

  接着,再创建方法来对不同的数据进行不同的方法调用:

    private static String getZeroName(String s) {
        String numberFinal;
        if (Integer.parseInt(s) <= 9999 && Integer.parseInt(s) >= 0) {
            numberFinal = nameChinese(Integer.parseInt(s));
        } else if (Integer.parseInt(s) <= 99999999 && Integer.parseInt(s) >= 10000) {
            numberFinal = nameWanChinese(Integer.parseInt(s));
        } else
           /* if (Integer.parseInt(s) <= 2147483647 && Integer.parseInt(s) >= 100000000) {
            numberFinal = nameYiChinese(Integer.parseInt(s));
        } else */ {
            numberFinal = "数据溢出";
        }
        return numberFinal;
    }

  注释掉的代码原本是为了输出亿元部分,但是经过多次尝试,未能创造出合适的方法,不甘心,不舍得删除,所以依旧留着------------------------------

  最后,对所得到的数据进行最后一次过滤:

    private static String getFinalChineseName(String s) {
        String zeroName = getZeroName(s);
        String finalName = zeroName.replace("零萬", "萬").replace("零拾零萬", "萬").replace("零佰零拾", "零").replace("零佰", "零").replace("零拾", "零").replace("零萬", "萬").replace("零億", "億");
        return finalName;
    }

  其实这步骤在思考过程中反而是最先想出来的,只不过这一步才进行了最彻底地实现.
  最后就是主方法进行调用,并添加计数器进行统计

public static void main(String[] args) {
        //char[] num = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
        //char[] digit = {'拾', '佰', '仟'};
        //char[] digitHuge = {'萬', '億'};
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个数字");
        String get = sc.next();
        String OK = getFinalChineseName(get);
        System.out.println(OK);//为了输出读法,方便进行验证
        int count = 0;
        for (int i = 1; i <= Integer.parseInt(get); i++) {
            count += getFinalChineseName(String.valueOf(i)).length();
        }
        System.out.println(count);
    }

完整代码

public class ReadAnyNumber {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        //char[] num = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
        //char[] digit = {'拾', '佰', '仟'};
        //char[] digitHuge = {'萬', '億'};
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个数字");
        String get = sc.next();
        String OK = getFinalChineseName(get);
        System.out.println(OK);
        int count = 0;
        for (int i = 1; i <= Integer.parseInt(get); i++) {
            count += getFinalChineseName(String.valueOf(i)).length();
        }
        long end = System.currentTimeMillis();
        System.out.println(count);
        System.out.println("从一读到一亿需要读" + (count + 2) + "个汉字,共耗时" + (end - start) + "毫秒");
    }
    private static String getFinalChineseName(String s) {
        String zeroName = getZeroName(s);
        String finalName = zeroName.replace("零萬", "萬").replace("零拾零萬", "萬").replace("零佰零拾", "零").replace("零佰", "零").replace("零拾", "零").replace("零萬", "萬").replace("零億", "億");
        return finalName;
    }

    private static String getZeroName(String s) {
        String numberFinal;
        if (Integer.parseInt(s) <= 9999 && Integer.parseInt(s) >= 0) {
            numberFinal = nameChinese(Integer.parseInt(s));
        } else if (Integer.parseInt(s) <= 99999999 && Integer.parseInt(s) >= 10000) {
            numberFinal = nameWanChinese(Integer.parseInt(s));
        } else
           /* if (Integer.parseInt(s) <= 2147483647 && Integer.parseInt(s) >= 100000000) {
            numberFinal = nameYiChinese(Integer.parseInt(s));
        } else */ {
            numberFinal = "数据溢出";
        }
        return numberFinal;
    }

    private static String nameWanChinese(int n) {
        String sN = String.valueOf(n);
        char[] arrN = sN.toCharArray();
        char[] arrStart = new char[arrN.length - 4];
        char[] arrEnd = new char[4];
        System.arraycopy(arrN, 0, arrStart, 0, arrN.length - 4);
        System.arraycopy(arrN, arrN.length - 4, arrEnd, 0, 4);
        StringBuffer strStart = new StringBuffer();
        for (char s : arrStart) {
            strStart.append(s);
        }
        String start = strStart.toString();
        StringBuffer strEnd = new StringBuffer();
        for (char s : arrEnd) {
            strEnd.append(s);
        }
        String end = strEnd.toString();
        if ((Integer.parseInt(end) < 1000 && Integer.parseInt(end) > 0) || (Integer.parseInt(start) % 10 == 0 && Integer.parseInt(start) >= 10&&Integer.parseInt(end)!=0)|| (Integer.parseInt(start) % 100 == 0 && Integer.parseInt(start) >= 100&&Integer.parseInt(end)!=0)|| (Integer.parseInt(start) % 1000 == 0 && Integer.parseInt(start) >= 1000&&Integer.parseInt(end)!=0)) {
            return (nameChinese(Integer.parseInt(start)) + "萬零" + nameChinese(Integer.parseInt(end)));
        } else {
            return (nameChinese(Integer.parseInt(start)) + "萬" + nameChinese(Integer.parseInt(end)));
        }
    }

    private static String nameChinese(int n) {
        String bigNumber = getBigNumber(n);
        char[] nnn = bigNumber.toCharArray();
        String digit = getDigit(n);
        char[] ddd = digit.toCharArray();
        String sA = String.valueOf(n);
        char[] arrA = sA.toCharArray();
        char[] arr2 = new char[arrA.length * 2 - 1];
        for (int i = 0; i < arrA.length * 2 - 1; i++) {
            if (i % 2 == 0) {
                //if(n%10 != 0)
                arr2[i] = nnn[i / 2];
            } else {
                arr2[i] = ddd[ddd.length - i / 2 - 1];
            }
        }
        StringBuffer str = new StringBuffer();
        for (char s : arr2) {
            str.append(s);
        }
        String s = str.toString().replace("零佰零拾", "零").replace("零佰", "零").replace("零拾", "零");

        String noTailNumber;
        if (n == 0) {
            noTailNumber = "";
        } else if (n % 100 == 0 && n >= 100) {
            noTailNumber = s.substring(0, s.length() - 2);
        } else if (n % 10 == 0 && n % 100 != 0 && n >= 10) {
            noTailNumber = s.substring(0, s.length() - 1);
        } else {
            noTailNumber = s;
        }
        return noTailNumber;
    }

    private static String getBigNumber(int numberR) {
        int number = numberR;
        char[] num = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
        String sNumber = String.valueOf(number);
        char[] arr = sNumber.toCharArray();
        char[] arr2 = new char[arr.length];
        for (int i = 0; i < arr.length; i++) {
            arr2[i] = num[Integer.parseInt(String.valueOf(arr[i]))];
        }
        StringBuffer str = new StringBuffer();
        for (char s : arr2) {
            str.append(s);
        }
        String numberBig = str.toString();
        return numberBig;
    }

    private static String getDigit(int numberR) {
        int number = numberR;
        char[] digit = {'拾', '佰', '仟'};
        String sNumber = String.valueOf(number);
        char[] arr = sNumber.toCharArray();
        char[] arr2 = new char[arr.length - 1];
        for (int i = 0; i < arr.length - 1; i++) {
            arr2[i] = digit[i];
        }
        StringBuffer str = new StringBuffer();
        for (char s : arr2) {
            str.append(s);
        }
        String digitDo = str.toString();
        return digitDo;
    }
}

  最后结果别忘记加2,因为还有个"一亿"没统计,哈哈
  顺便加入时间,看看我的笨方法需要耗时多久…………

//输出结果
请输入一个数字
99999999
玖仟玖佰玖拾玖萬玖仟玖佰玖拾玖
1412990003
从一读到一亿需要读1412990003个汉字,共耗时222302毫秒

缺点

  显而易见,太坑了,居然耗时这么久!!
  而且此方法也没有对亿进行分析!!

请教

  希望各位大神对我这个方法提提意见,或者有更好的方法,让我学习学习

评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值