从一读到一亿需要读多少个汉字?
从一读到一亿需要读多少个汉字?
- 题目分析
- 思路分析
- 方法改进
- 具体思路
- 完整代码
- 缺点
- 请教
题目分析
首先对读法做一下规范,我是做过两年审计工作,所以习惯于采用会计的大写方式
例如(没有测试所有格式,仅测试了如下个别代表性数据;这里的十均表示为"壹拾",间隔有零均读零):
数据 | 大写 | 数据 | 大写 | 数据 | 大写 |
---|---|---|---|---|---|
1 | 壹 | 10,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毫秒
缺点
显而易见,太坑了,居然耗时这么久!!
而且此方法也没有对亿进行分析!!
请教
希望各位大神对我这个方法提提意见,或者有更好的方法,让我学习学习
从一读到一亿需要读多少个汉字?相关推荐
- 产品经理要读什么书?怎么读?
产品相关知识可以在:http://www.aipingce.com/进行学习,本文转自:http://www.aipingce.com/article-22960-1.html 首先,我个人还是非常推 ...
- oracle 优化逻辑读过高,详述逻辑读与arraysize的关系
我们都知道,数据块是oracle最基本的读写单位,但用户所需要的数据,并不是整个块,而是块中的行,或列.当用户发出SQL语句时,此语句被解析执行完毕,就开始了数据的抓取阶段,在此阶段,服务器进程会先将 ...
- mysql 快照读 幻读,InnoDB的MVCC如何解决不可重复读和快照读的幻读,当前读用next-key解决幻读...
InnoDB默认的隔离级别是RR(可重复读),可以解决脏读和不可重复读,只解决了快照读情况下的幻读问题,当前读情况下解决幻读问题得靠next-key锁. mysql如何实现避免幻读: 在快照读读情况下 ...
- 开机预读快还是不预读快_WIN 7下的超级预读比VISTA要好,改进不少!推荐开启超级预读!...
预读技术是微软vista和windows7默认开启的程序,原意是增加程序运行和开机速度,但事与愿违,该技术已经变成与UAC几乎一样的垃圾,普通用户建议关闭,原因有: 1.程序本身额外增加系统负担,启用 ...
- kubernetes英语怎么读_英语音标怎么读?如何从零基础英语音标入门英语口语学习...
英语是学习英语的基础,学好音标才能够提高英语发音的准确性,为后面更复杂的口语练习打下坚实的地基,同时也对词汇的记忆有着很大的影响. 英语趣配音特别整理汇总了48个音标及发音技巧供大家参考学习 音标 单 ...
- mysql实战20 | 幻读是什么,幻读有什么问题?
在上一篇文章最后,我给你留了一个关于加锁规则的问题.今天,我们就从这个问题说起吧. 为了便于说明问题,这一篇文章,我们就先使用一个小一点儿的表.建表和初始化语句如下(为了便于本期的例子说明,我把上篇文 ...
- 中国地质大学英语语音学习笔记(四):英语连读——弱读、冠词连读方法(包括元音字母前添加an的原因)和词间辅音加元音的连读方法
前言 本笔记整理于中国地质大学(武汉)的一门英语发音课程:英语语音,的第九,十单元的文档资料.包括冠词连读(不定冠词连读,定冠词连读,元音字母前用an的原因),弱读和辅音加元音连读的发音技巧.整理 ...
- 茜在人名可以读xi吗_茜读xi还是qian?
01 茜可以读xi,也可以读qian,通常用于外国女子名字译音时多读xī,而qiàn多用于中国名.茜,本义是草名即"茜草"读音为qiàn时,指茜草,在古汉语中也指"深红& ...
- mysql 幻读 mvcc_MVCC 能解决幻读吗?
MySQL通过MVCC(解决读写并发问题)和间隙锁(解决写写并发问题)来解决幻读 MySQL InnoDB事务的隔离级别有四级,默认是"可重复读"(REPEATABLE READ) ...
最新文章
- c语言 真假条件跳转语句,什么是无条件跳转语句(C++)
- Python十大装腔语法
- 两帧点云刚性配准的ICP算法
- 华御密盾智能防信息泄密系统
- python微信推送消息_Python编程之微信推送模板消息功能示例
- raid0 raid1 raid5 raid10工作模式的工作原理及特点
- NamingException
- [NOI2009]管道取珠
- 如何解决“企业内控”存在的形式化问题
- ImageView和ImageButton的区别
- android studio javah命令,Android Studio 配置 javah 和 ndk-build 快捷编译
- HTML---鼠标悬停导航栏变颜色
- 中国大陆芯片设计企业名单
- 企业微信每日定时自动上报
- 格式化 命令 linux,linux格式化命令(linux格式化磁盘命令fdisk详解)
- idea 去掉author波浪线
- 计算机英语句子及译文,英语经典句子
- 欲登千层楼,又何惧寒风
- nn.Linear()函数详解
- IDEA 配置Go环境,编写Golang代码,学习笔记(一)