达内广州C++学院|c++培训|广州达内科技C++/C#培训|.NET培训|IT培训|达内广州岗顶中心 达内广州C++学院|c++培训|广州达内科技C++/C#培训|.NET培训|IT培训|达内广州岗顶中心
java程序员
 当前位置:主页 > 高端课程 > java程序员 >

中文数字阿拉伯数字相互转换

时间:2020-07-22  来源:未知  作者:广州达内培训

目录

  • 中文数字转阿拉伯数字
    • 解题思路
      • 各个击破
      • 友情提醒
  • 阿拉伯数字转中文数字
  • 测试
  • 源码
  • # 加入战队
    • 微信公众号

阿拉伯数字肯定是使用最广泛的符合之一了。我们日常生活都离不开数字。中文下的数字是中国特色的数字。开发中也会遇到需要两者相互转换的需求。今天就来实现下。

中文数字转阿拉伯数字

  • 想上面的数字一样。假设我们的中文数字是【一亿七千七十九万七千一百九十七】。

解题思路

  • 首先我们需要将上面中文数字按阿拉伯数字进行分离。这里我们先提出一个思想前提: 亿、万 这种是高级单位;千、百、十这种是低级单位。所以我们先按高级单位将上面的进行拆分。

  • 我们得到上面的三个数字。分别是【一亿】、【七千零七十九万】、【七千一百九十七】。下面我们针对这三个数字进行翻译。

各个击破

  • 仔细分析下上面三个中文数字,不难得出结论-上面三个数字去掉高级单位剩下的都只有低级单位了。这也是我们实现的重点【低级单位内的数字转换】

  • 我们将三个数字分别转换完成之后,剩下的就是将他们组合。组合的问题也就是中间补零和去零的操作。

  • 【七千零七十九万】去掉高级单位【七千零七十九】我们翻译也很简单就是将低级单位去掉变成【七零七九】及【7079】。那么上面的三位数字分别是

中文数字 去掉单位后 数字映射
一亿 1
七千零七十九万 七零七九 7079
七千一百九十七 七一九七 7197
  • 三位数字翻译好之后我们进行阿拉伯数字的拼接就完成了。 170797197

友情提醒

  • 上面的数字翻译的很是顺利。但是又这么一类数字总是事与愿违。
  • 【一亿零七十九万零一百九十七】==【100790197】
  • 按照上面的思路我们会有如有推理
中文数字 去掉单位后 数字映射
一亿 1
零七十九万 零七九 079
零一百九十七 零一九七 0197
  • 根据表格我们拼接得到的数字是【10790197】。这个时候问题就大了去了。我们丢失了一位0。原因也很简单在中文数字中在同一高级单位维度里连续多个零的出现会同一读零。但是阿拉伯数字中确实实实在在的占位的。所以这里就会缺失一位零。

  • 这里的情况是一开始笔者没哟注意到的。但是后来改正了。所以上面提到的合并方法是没有问题的。上面是进行数字化乘以10000的。所以这里的0也不会丢失的。

  • 正确的拼接方案是 ((110000)+079)10000+0197=100790197

  • 这种问题反向过来同样值得注意,在阿拉伯转中文数字的时候我们需要注意0到底代表几个0

阿拉伯数字转中文数字

  • 【100790197】 ==【一亿零七十九万零一百九十七】

  • 【100000197】 ==【一亿零一百九十七】

  • 下面我们将对上面的两个阿拉伯数字进行解析转换。同样我们对他们进行高位分离。这里需要注意的是我们需要从低位到高位方向进行分离

  • 分离是从低位到高位。但是我们转换却要从高位到低位。顺序不能错。在我们阿拉伯数字转中文数字的时候非零数字注解映射转换就行了。但是遇到0的时候我们需要有一下三个条件才能转换,否则就要忽略。

    • 第一次遇到0
    • 数字为0
    • 统一高位单元内后面并不是全是0
  • 简单解释下上面三个。第一个通过一个状态为就能搞定。第二个其实就是保险点。可有可无。最重要第三点遇零后后面不能全是0.这个时候我们才可以将当前位置0翻译成零。

  • 每个非零数字翻译后需要加上低级单位的。

  • 所以上面的0079我们翻译的是【零七十九】

  • 但是零七九并不是真正的汉字数字。所以我们在每一次高位翻译完成之后需要加上高位单位。所以【0079】==【零七十九万】

  • 所以我们得出如下

阿拉伯数字 数字映射
1 一亿
0079 零七十九万
0197 零一百九十七
  • 所以【100790197】 ==【一亿零七十九万零一百九十七】
阿拉伯数字 数字映射
1 一亿
0000
0197 零一百九十七
  • 在加入高级单位时我们需要判断高级单位内数字是否有效。因为我们上面三个原因。所以0000对应的中文数字就是空字符串。这里我们认为是无效中文数字。所以万单位也就没有了。所以【100000197】==【一亿零一百九十七】

测试

  • 光谈理论不讲实践都是扯淡。下面我们需要对我们的设计进行验证。如何验证嗯。好在我们实现的【中文数字转阿拉伯数字】、【阿拉伯数字转中文数字】 。 那么我们直接通过两个方法相互转换。看看最终是不是原来的数据就能验证出来了。话不多说、上代码

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));

  • 测试后的正确率是1 。 也就是0差错。
  • 欢迎指出错误。

源码


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));
    }
}


加入战队

# 加入战队

微信公众号

微信公众号




上一篇:Java8(五) 接口默认方法
下一篇:怎么找出消耗 CPU 的罪魁祸首?!

友情链接:
  • 全球最大晶圆代工半导体制造厂,台积电斥资订购艾斯摩尔机器设备
  • 英特尔依然是那个英特尔,且看英特尔的城防体系
  • 支持双 DRAM 内存接口,慧荣企业级 SSD 主控方案披露
  • 在全球被反垄断罚款,冤!高通到底哪里得罪了欧盟?
  • 强强联合!万业、微电子所和芯鑫共同打造全新半导体设备
  • 复旦大学校长称:对于集成电路产业发展,大学应该主动担当
  • 技术再升级!无锡中科芯攻克晶圆级再布线及晶圆级凸点制备关键技
  • 聚力!万业企业设立集成电路装备集团,提供自主可控设备
  • 德州仪器C2000微控制器增强连通性和控制性
  • 英特尔打出降价策略,以免被竞争对手 AMD 打败?
  • 贸易摩擦的闹剧没有赢家,苹果有勇气离开中国吗?
  • 图像信号与视觉处理器的发展趋势
  • 真干快消品定位方案班(第二期)火热开班
  • Java集合 ArrayList原理及使用
  • TDD(测试驱动开发)死了吗?
  • JAVA基础之XML相关
  • javaweb项目搭建ehcache缓存系统
  • 每日一码——字符串统计
  • 一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生
  • 九:模板方法模式
  • 十二:命令模式(人员解耦和)
  • Java 转PPT为图片、PDF、SVG、XPS、ODP以及PPT和PPTX互转
  • SpringCloud学习(SPRINGCLOUD微服务实战)一
  • 记一次微信网页授权后获取用户信息并重定向
  • 速途新营销五点实战洞察解码“品效合一”
  • 十一:外观模式详解(Service,action与dao)
  • 手把手教你学会 基于JWT的单点登录
  • mysql锁机制总结,以及优化建议
  • 解决多个版本jar包冲突【jar内包名重命名】
  • 中国首张5G终端电信设备进网许可证 华为Mate 20 X 5G版入网
  • RPC之Thrift
  • 高级Java工程师必备 ----
  • 天猫618期间实物支付GMV增长38.5%
  • 换季了,老板你的库存处理好了吗?
  • 从“618”大数据看中国消费新活力
  • 小米生态链:贵在格局感与收放度
  • CODING 2.0 企业级持续交付解决方案
  • 老铁奇趴“新京济” 快手*京东618战报出炉
  • 中小企业新媒体运营基本技能
  • 上汽大通房车再度携手LINE FRIENDS 魔都巡游顺利开启
  • 华为高端手机国内市场份额超苹果夺得榜首
  • 中国智能制造分析报告
  • iPlus艾加营销助力腾讯广告牵手吴晓波 推进商业IP变现
  • 2019世界新能源汽车大会7月1日将在海南举行
  • 区域酒企如何转型突围
  • 时时彩论坛
  • 五星体育斯诺克
  • 北单比分直播
  • 河北11选5走势图
  • 福建体彩36选7开奖结果
  • 九龙图库下载