目录
阿拉伯数字肯定是使用最广泛的符合之一了。我们日常生活都离不开数字。中文下的数字是中国特色的数字。开发中也会遇到需要两者相互转换的需求。今天就来实现下。
仔细分析下上面三个中文数字,不难得出结论-上面三个数字去掉高级单位剩下的都只有低级单位了。这也是我们实现的重点【低级单位内的数字转换】
我们将三个数字分别转换完成之后,剩下的就是将他们组合。组合的问题也就是中间补零和去零的操作。
【七千零七十九万】去掉高级单位【七千零七十九】我们翻译也很简单就是将低级单位去掉变成【七零七九】及【7079】。那么上面的三位数字分别是
中文数字 | 去掉单位后 | 数字映射 |
---|---|---|
一亿 | 一 | 1 |
七千零七十九万 | 七零七九 | 7079 |
七千一百九十七 | 七一九七 | 7197 |
中文数字 | 去掉单位后 | 数字映射 |
---|---|---|
一亿 | 一 | 1 |
零七十九万 | 零七九 | 079 |
零一百九十七 | 零一九七 | 0197 |
根据表格我们拼接得到的数字是【10790197】。这个时候问题就大了去了。我们丢失了一位0。原因也很简单在中文数字中在同一高级单位维度里连续多个零的出现会同一读零。但是阿拉伯数字中确实实实在在的占位的。所以这里就会缺失一位零。
这里的情况是一开始笔者没哟注意到的。但是后来改正了。所以上面提到的合并方法是没有问题的。上面是进行数字化乘以10000的。所以这里的0也不会丢失的。
正确的拼接方案是 ((1 10000)+079) 10000+0197=100790197
这种问题反向过来同样值得注意,在阿拉伯转中文数字的时候我们需要注意0到底代表几个0
【100790197】 ==【一亿零七十九万零一百九十七】
【100000197】 ==【一亿零一百九十七】
下面我们将对上面的两个阿拉伯数字进行解析转换。同样我们对他们进行高位分离。这里需要注意的是我们需要从低位到高位方向进行分离
分离是从低位到高位。但是我们转换却要从高位到低位。顺序不能错。在我们阿拉伯数字转中文数字的时候非零数字注解映射转换就行了。但是遇到0的时候我们需要有一下三个条件才能转换,否则就要忽略。
简单解释下上面三个。第一个通过一个状态为就能搞定。第二个其实就是保险点。可有可无。最重要第三点遇零后后面不能全是0.这个时候我们才可以将当前位置0翻译成零。
每个非零数字翻译后需要加上低级单位的。
所以上面的0079我们翻译的是【零七十九】
但是零七九并不是真正的汉字数字。所以我们在每一次高位翻译完成之后需要加上高位单位。所以【0079】==【零七十九万】
所以我们得出如下
阿拉伯数字 | 数字映射 |
---|---|
1 | 一亿 |
0079 | 零七十九万 |
0197 | 零一百九十七 |
阿拉伯数字 | 数字映射 |
---|---|
1 | 一亿 |
0000 | |
0197 | 零一百九十七 |
Integer right = 0; Integer total = 10000000; List<Map<String, Object>> list = new ArrayList<>(); for (int i = 0; i < total; i++) { Integer number = MathUtil.getInstance().getRandom(1, 1000000000); //System.out.println(i); //Integer number = 400001989; String chinese = DigitUtil.getInstance().getNumberFromAlabo(number.toString()); String alabo = DigitUtil.getInstance().getNumberFromChinese(chinese); boolean equals = alabo.equals(number.toString()); if (equals) { right++; } else { Map<String, Object> map = new HashMap<>(); map.put("number", number); map.put("alabo", alabo); map.put("chinese", chinese); list.add(map); } } for (Map<String, Object> map : list) { System.out.println(map); } System.out.println("成功率:"+Double.valueOf(right/(double)total));
package org.zxhtom.utils; import org.zxhtom.constant.ChineseNumber; import java.util.*; /** * @package org.zxhtom.utils * @Class DigitUtil * @Description 数字工具类 * @Author zhangxinhua * @Date 19-7-2 下午3:47 */ public class DigitUtil { private static DigitUtil util; public static DigitUtil getInstance() { if (null == util) { util = new DigitUtil(); } return util; } /** * 中文数字转阿拉伯数字 * 一万两千三百五十四 --> 12354 * @param chinese 阿拉伯数字 * @return 中文数字 */ public String getNumberFromChinese(String chinese) { String result = "0"; //将中文数字按四位进行截取。这样每一位里只有单一 List<String> lists = new ArrayList<>(); //暂时未使用到 int lastLevelIndex = 0; //循环遍历,目的是将亿万进行分离 for (int i = ChineseNumber.highLevel.size()-1; i>=0; i--) { //判断亿万单位出现索引 int levelIndex = chinese.indexOf(ChineseNumber.highLevel.get(i)); if (levelIndex>0) { //表示有单位索引 , 将单位前数据进行截取装入lists中。后面的继续循环截取 lists.add(chinese.substring(0, levelIndex)); chinese = chinese.substring(levelIndex+1); } else if (levelIndex == -1) { //表示已经是最低单位了,不超过万。直接加入lists中 , 这里情况对应的是高位分离后,次高位开头是0的情况 lists.add(ChineseNumber.number.get(0)); } else if (levelIndex == 0) { while (levelIndex > 1) { levelIndex--; lists.add(ChineseNumber.number.get(0)); } //直接加入 lists.add(chinese); } } //针对分离的四位数据,进行单独翻译 for (int i = 0; i < lists.size(); i++) { //未使用 Integer highLevelIndex = lists.size() - i - 1; //获取单元数据 String single = lists.get(i); //对单元数据进行翻译 。 String nextResult = getNumberFromFChinese(single); //lists中每位都是4位数截取 ,所以这里需要乘以10000进行叠加 Long next = Long.valueOf(Integer.valueOf(result) * (int)(Math.pow(10, 4)) + Integer.valueOf(nextResult)); result = next.toString(); } //将开头0抹掉 result = result.replaceFirst("^(0+)", ""); return result; } /** * 通过中文数字获取4位数阿拉伯数字 * 万以内的数据转换 * @param single * @return */ private String getNumberFromFChinese(String single) { String result = "0"; Integer highIndex = 1; for (int i = 0; i < single.length(); i++) { String str = String.valueOf(single.charAt(i)); int unit = ChineseNumber.level.indexOf(str); int number = ChineseNumber.number.indexOf(str); if (unit == -1) { //当前数字是万以内的单位即 千百十其中之一 int next = 0; if (i < single.length() - 1) { //如果不是最后一位,则需要考虑当前位的权重 next = ChineseNumber.level.indexOf(String.valueOf(single.charAt(i + 1))); } result=String.valueOf(Integer.valueOf(result)+number * (int) (Math.pow(10, next))); } } //权重叠加 result = ""+Integer.valueOf(result) * (int) (Math.pow(10, highIndex - 1)); return result; } /** * 阿拉伯数字转中文数字 * 12354 --> 一万两千三百五十四 * @param alabo 阿拉伯数字 * @return 中文数字 */ public String getNumberFromAlabo(String alabo) { String result = ""; List<String> list = new ArrayList<>(); for (int length = alabo.length()-1; length >= 0; length--) { list.add(String.valueOf(alabo.charAt(length))); } List<List<String>> lists = CollectionUtil.averageSize(list, 4); Collections.reverse(lists); if (CollectionUtil.isNotEmpty(lists)) { for (int index=0;index<lists.size();index++) { List<String> singleNumList = lists.get(index); //反转集合 Collections.reverse(singleNumList); //默认0 false Boolean zeroflag =false; String chinese = ""; for (int j=0 ; j<singleNumList.size();j++) { Integer number = Integer.valueOf(singleNumList.get(j)); if (number == 0 && !zeroflag && afterNotAllZero(singleNumList, j)) { //第一次遇到0 且后面有小单位内并不是全为0 chinese += ChineseNumber.number.get(number); //修改遇零状态true zeroflag = true; } else if(number!=0) { //映射出对应的中文数字 chinese += ChineseNumber.number.get(number) + ChineseNumber.level.get(singleNumList.size()-j-1); } } if (index==lists.size()&&chinese.substring(0, 1).equals(ChineseNumber.number.get(0))) { //条件永远不成立。 chinese = chinese.substring(1); } //并不是全部为0,该高级单位才会生效 if (chinese.length()>0&&!ChineseNumber.highLevel.contains(chinese.substring(chinese.length() - 1))) { result += chinese + ChineseNumber.highLevel.get(lists.size() - 1 - index); } } } return result; } /** * 判断singleNumList在j位置之后是否全是0 * @param singleNumList * @param j * @return */ private boolean afterNotAllZero(List<String> singleNumList, int j) { for (int i = j+1; i < singleNumList.size(); i++) { if (!"0".equals(singleNumList.get(i))) { return true; } } return false; } public static void main(String[] args) { Integer right = 0; Integer total = 10000000; List<Map<String, Object>> list = new ArrayList<>(); for (int i = 0; i < total; i++) { Integer number = MathUtil.getInstance().getRandom(1, 1000000000); //System.out.println(i); //Integer number = 400001989; String chinese = DigitUtil.getInstance().getNumberFromAlabo(number.toString()); String alabo = DigitUtil.getInstance().getNumberFromChinese(chinese); boolean equals = alabo.equals(number.toString()); if (equals) { right++; } else { Map<String, Object> map = new HashMap<>(); map.put("number", number); map.put("alabo", alabo); map.put("chinese", chinese); list.add(map); } } for (Map<String, Object> map : list) { System.out.println(map); } System.out.println("成功率:"+Double.valueOf(right/(double)total)); } }