logo头像

学如逆水行舟,不进则退!!!

文章目录

各种格式数字相互转换

本文于727天之前发表,文中内容可能已经过时。

[TOC]

作为一名程序员,随着年龄的增长我们的积累会越来越多。工作这么就了也做过不少的工具类封装,但是没有过集中整理,有些东西都是很重复的。所以决定开辟一个模块专门梳理平时写的或者借鉴的工具类介绍。对应的会在我的基础工程中进行源码呈现bottom

功能介绍

在一次开发中数据库中存储的是中文数字类型,需求是我需要按数字进行排序,我想当然的用order by 发现中文的数字并不是按大小排序的。他是安装中文数字对应的ascll码进行排序的。这就展开了我们今天需要讨论的一个工具类–DigitUtil
该工具类还是采用单列模式开发,提供了两个功能。

中文数字转阿拉伯数字

代码示例

/**
 * 中文数字转阿拉伯数字
 *  一万两千三百五十四 --> 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.add(chinese.substring(0, levelIndex));
            chinese = chinese.substring(levelIndex+1);
        } else if (levelIndex == -1) {
            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);
        Long next = Long.valueOf(Integer.valueOf(result) * (int)(Math.pow(10, 4)) + Integer.valueOf(nextResult));
        result = next.toString();
    }
    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;
}

代码解读

首先默认输出结果为0

- 如果没有数据则默认转换为0

然后将数据按4位数切割。一亿、一万、一。这样每四位四位切割

- 通过亿,万这些高级别单位讲中文数字转换为四位数字为一组的集合  

解读4位数字的中文数字

- 我们首先定义万以内的单位分别有千百十一这四个基本单位。我们一个一个看字符串是属于单位集合还是属于数字集合。有个特殊的情况就是在遇到中文数字零的时候我们转换的时候需要注意需要填补几个0,这里我采取的是记录上一次的基本单位和0的下一次的基本单位之间的差值就是补0的个数。

阿拉伯数字转中文数字

代码示例


/**
 * 阿拉伯数字转中文数字
 * 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)) {
                    chinese += ChineseNumber.number.get(number);
                    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);
            }
            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;
}

代码解读

###同样将阿拉伯数字按4位截取

  • 通过集合将集合分拆成4位一组

###在4为数中遇到0需要处理上述问题中的反向,遇到多个0注意转成一个零

  • 在从高位向低位遍历时,需要注意遇到连续多个0转换成一个零。因为阿拉伯数字是不会有0开头的,所以合并最后不要处理开始为零的数据
  • 最后将各个四位数字转换的四位阿拉伯数字拼接在一起就可以了

未来规划

  • 未来根据需求会讲英文的数字和中文的数字和阿拉伯数字三者进行互相转换。目前的阿拉伯数字和中文数字在亿级别的层面上正确率100% , 感兴趣的伙伴可以持续关注加入战队

# 加入战队

微信公众号

微信公众号

主题

封面

上一篇
坚持原创技术分享,您的支持将鼓励我继续创作!

评论系统未开启,无法评论!