金钱数字转换成中文数值

简介: 金钱数字转换成中文数值

金钱数字转换成中文数值


关于中文数值表示参考链接:

https://baike.baidu.com/item/%E4%B8%AD%E6%96%87%E6%95%B0%E5%AD%97/2921705?fr=aladdin

package top.simba1949;
import java.util.*;
/**
 * 最高支持:1京 减 0.01
 *
 * 设计思路:
 * 将字符串通过小数点分割为整数部分和小数部分(小数部分取2位)
 *
 * 整数部分处理思路:
 *      数字字符串从后往前数,每8位一个单元,千百十万千百十个+单位
 *      每个单元,第三位是万位,需要特殊处理,
 *          |->如果万前面存在数字,但是万位没有数值,需要添加上万,
 *          |->如果万前面没有数值同时万没有数值,不用添加
 *
 * 小数部分处理思路:
 *      判断是否是否存在
 *          |->存在,先取第一位小数位做角,然后判断长度是否大于2,
 *          |    |->不大于等于2,直接返回
 *          |    |->大于等于2再取第二位小数做分返回
 *          |->不存在,返回`整`
 * @author anthony
 * @date 2021/1/26
 */
public class MoneyUtils {
    private static final String NUMBER_ZERO_STR = "0";
    private static final String NUMBER_ONE_STR = "1";
    private static final String NUMBER_TWO_STR = "2";
    private static final String NUMBER_THREE_STR = "3";
    private static final String NUMBER_FOUR_STR = "4";
    private static final String NUMBER_FIVE_STR = "5";
    private static final String NUMBER_SIX_STR = "6";
    private static final String NUMBER_SEVEN_STR = "7";
    private static final String NUMBER_EIGHT_STR = "8";
    private static final String NUMBER_NINE_STR = "9";
    private static final String NUMBER_POINT_STR = ".";
    private static final String DELIMITER_DECIMAL_POINT = "\\.";
    private static final String DELIMITER_COMMA = ",";
    private static final String CN_NUMBER_ZERO_STR = "零";
    private static final String CN_NUMBER_ONE_STR = "壹";
    private static final String CN_NUMBER_TWO_STR = "贰";
    private static final String CN_NUMBER_THREE_STR = "叁";
    private static final String CN_NUMBER_FOUR_STR = "肆";
    private static final String CN_NUMBER_FIVE_STR = "伍";
    private static final String CN_NUMBER_SIX_STR = "陆";
    private static final String CN_NUMBER_SEVEN_STR = "柒";
    private static final String CN_NUMBER_EIGHT_STR = "捌";
    private static final String CN_NUMBER_NINE_STR = "玖";
    private static final String CN_NUMBER_TEN_STR = "拾";
    private static final String CN_NUMBER_HUNDRED_STR = "佰";
    private static final String CN_NUMBER_THOUSAND_STR = "仟";
    private static final String CN_NUMBER_TEN_THOUSAND_STR = "万";
    private static final String CN_NUMBER_BILLION_STR = "亿";
    private static final String CN_NUMBER_TRILLION_STR = "兆";
    private static final String RMB_UNIT_YUAN = "圆";
    private static final String RMB_UNIT_JIAO = "角";
    private static final String RMB_UNIT_FEN = "分";
    private static final String NO_POINT = "整";
    /**
     * 数值与中文数字映射关系
     */
    private static Map<String, String> numberMap = new HashMap<>(16);
    /**
     * 长度与单位映射关系
     */
    private static Map<Integer, String> unitMap = new HashMap<>(16);
    /**
     * 从后往前数,每8个为单位,获取单位数值,千,百,十,万,千,百,十,一
     */
    private static Map<Integer, String> unitMap4Digits = new HashMap<>(16);
    static {
        numberMap.put(NUMBER_ZERO_STR, CN_NUMBER_ZERO_STR);
        numberMap.put(NUMBER_ONE_STR, CN_NUMBER_ONE_STR);
        numberMap.put(NUMBER_TWO_STR, CN_NUMBER_TWO_STR);
        numberMap.put(NUMBER_THREE_STR, CN_NUMBER_THREE_STR);
        numberMap.put(NUMBER_FOUR_STR, CN_NUMBER_FOUR_STR);
        numberMap.put(NUMBER_FIVE_STR, CN_NUMBER_FIVE_STR);
        numberMap.put(NUMBER_SIX_STR, CN_NUMBER_SIX_STR);
        numberMap.put(NUMBER_SEVEN_STR, CN_NUMBER_SEVEN_STR);
        numberMap.put(NUMBER_EIGHT_STR, CN_NUMBER_EIGHT_STR);
        numberMap.put(NUMBER_NINE_STR, CN_NUMBER_NINE_STR);
    }
    static {
        unitMap4Digits.put(1, "");
        unitMap4Digits.put(2, CN_NUMBER_TEN_STR);
        unitMap4Digits.put(3, CN_NUMBER_HUNDRED_STR);
        unitMap4Digits.put(4, CN_NUMBER_THOUSAND_STR);
        unitMap4Digits.put(5, CN_NUMBER_TEN_THOUSAND_STR);
        unitMap4Digits.put(6, CN_NUMBER_TEN_STR);
        unitMap4Digits.put(7, CN_NUMBER_HUNDRED_STR);
        unitMap4Digits.put(8, CN_NUMBER_THOUSAND_STR);
    }
    static {
        // 圆
        unitMap.put(1, RMB_UNIT_YUAN);
        // 亿
        unitMap.put(2, CN_NUMBER_BILLION_STR);
        // 兆
        unitMap.put(3, CN_NUMBER_TRILLION_STR);
    }
    /**
     * 钱币
     * 数字转换成中文大写
     * 目前最大支持一兆
     * @return
     */
    public static String moneyNumber2CnNumber(String original){
        if (null == original || original.trim().isEmpty()){
            return "";
        }
        // beforePoint 表示整数部分,afterPoint表示小数部分
        String beforePoint, afterPoint= "";
        String originalTrim = original.replace(" ", "").trim();
        if (originalTrim.contains(NUMBER_POINT_STR)){
            // 存在小数点
            String[] split = originalTrim.split(DELIMITER_DECIMAL_POINT);
            beforePoint = split[0].trim();
            afterPoint = split[1].trim();
        }else {
            // 不存在小数点
            beforePoint = originalTrim;
        }
        return integerDealWith(beforePoint) + decimalDealWith(afterPoint);
    }
    /**
     * 整数部分处理方式
     * @param integer
     * @return
     */
    private static String integerDealWith(String integer){
        if (null == integer || integer.trim().isEmpty()){
            return "";
        }
        // 从后往前数,每8位添加一个分割符号,
        List<String> list = new ArrayList<>();
        char[] chars = integer.trim().toCharArray();
        int j = 1;
        for (int i = chars.length - 1; i >= 0; i--) {
            list.add(String.valueOf(chars[i]));
            if (j%8 == 0){
                list.add(DELIMITER_COMMA);
            }
            j++;
        }
        Collections.reverse(list);
        // 获取带有分割符`,`的字符串
        StringBuilder builder = new StringBuilder();
        list.forEach(builder::append);
        String str = builder.toString();
        // 去掉头部逗号
        if (str.startsWith(DELIMITER_COMMA)){
            str = str.replaceFirst(DELIMITER_COMMA, "");
        }
        // 每8位分割后处理
        StringBuilder resultBuilder = new StringBuilder();
        String[] split = str.split(DELIMITER_COMMA);
        int length = split.length;
        for (int i = 0; i < length; i++) {
            resultBuilder.append(integerDealWithCoreWithUnit(split[i], unitMap.get(length - i)));
        }
        return resultBuilder.toString();
    }
    /**
     * 数字按照 `千万百万十万,万千百十个` 排序
     * @param number
     * @param unit 最后的单位
     * @return
     */
    private static String integerDealWithCoreWithUnit(String number, String unit){
        if (null == number || number.trim().isEmpty() || null == unit){
            return "";
        }
        StringBuilder builder = new StringBuilder();
        switch (number.length()){
            case 7: number = "0" + number;break;
            case 6: number = "00" + number;break;
            case 5: number = "000" + number;break;
            case 4: number = "0000" + number;break;
            case 3: number = "00000" + number;break;
            case 2: number = "000000" + number;break;
            case 1: number = "0000000" + number;break;
        }
        int length = number.length();
        int j = length;
        for (int i = 0; i < length; i++) {
            String value = String.valueOf(number.charAt(i));
            if (!NUMBER_ZERO_STR.equals(value)){
                builder.append(numberMap.get(value)).append(unitMap4Digits.get(j));
            }else {
                // 8位数,第四位数没有值但是前面有值
                if (i == 3 && builder.length() > 0){
                    builder.append(CN_NUMBER_TEN_THOUSAND_STR);
                }
            }
            j--;
        }
        // 添加最后的单位
        if (builder.length() > 0){
            builder.append(unit);
        }
        return builder.toString();
    }
    /**
     * 小数部分处理方式
     * @param decimal
     * @return
     */
    private static String decimalDealWith(String decimal){
        if (null == decimal || decimal.trim().isEmpty()){
            return NO_POINT;
        }
        // 自取两位小数
        StringBuilder builder = new StringBuilder();
        // 角
        String decimalTrim = decimal.trim();
        String tenthsNumberStr = String.valueOf(decimalTrim.charAt(0));
        if (!NUMBER_ZERO_STR.equals(tenthsNumberStr)){
            builder.append(numberMap.get(tenthsNumberStr)).append(RMB_UNIT_JIAO);
        }
        // 分
        if (decimalTrim.length() >= 2){
            String percentileNumberStr = String.valueOf(decimalTrim.charAt(1));
            if (!NUMBER_ZERO_STR.equals(percentileNumberStr)){
                builder.append(numberMap.get(percentileNumberStr)).append(RMB_UNIT_FEN);
            }
        }
        return builder.toString();
    }
    private MoneyUtils() {
    }
}


目录
相关文章
|
9月前
|
人工智能 网络性能优化 异构计算
阿里云基础网络技术5篇论文入选全球网络顶会NSDI
阿里云在NSDI 2025会议上发表5篇主会论文,涵盖大模型训练网络故障诊断、仿真、性能优化及CDN流控算法等领域。其中,《Evolution of Aegis》提出两阶段演进路线,显著降低故障诊断时间;《SimAI》实现高精度大模型训练模拟;其他论文分别在CDN拥塞控制、GPU解耦推理和容器网络性能优化上取得突破。这些成果为AI大模型时代的云计算基础设施发展提供了重要支持。NSDI是计算机网络与系统研究领域的顶级会议,本次录取率仅12.5%。
|
机器学习/深度学习 Web App开发 数据可视化
过节福利 | MMCV Hook 超全使用方法(下)
在训练过程中,通常有十个关键位点,如下图所示,从训练开始到结束,所有关键位点已用红色标出,共有 10 个。我们可以在这十个位点插入各种逻辑,例如加载模型权重、保存模型权重。而我们将同一类型的逻辑组织成一个 Hook。因此,MMCV 中 Hook 的作用就是训练和验证模型时,在不改变其他代码的前提下,灵活地在不同位点插入定制化的逻辑。
2580 0
过节福利 | MMCV Hook 超全使用方法(下)
|
数据采集 SQL 开发框架
菜刀webshell特征分析
菜刀webshell特征分析
704 0
菜刀webshell特征分析
|
Android开发
Android 的输入法适配设置windowSoftInputMode方式
用户评论开发过程中通常需要和EditText控件打交道,编辑框通常编程过程中最常见的就是和软键盘做交互操作。在用户最初进入编辑评论时有时希望直接展示软键盘,减少用户选中输入框操作,最好是保证输入框不被软件盘覆盖住。android:windowSoftInputMode属性就包含了实现这些交互方式的属性,主要分成两个部分,一个是控制软件盘展示或隐藏的state开头属性值,一个是控制展示输入框的Window适配效果的adjust开头属性值,通常都是两个使用或(|)指定键盘盘和Windwo适配效果,最常见的Adjust属性值解释如下:
757 152
Android 的输入法适配设置windowSoftInputMode方式
|
分布式计算 Kubernetes 大数据
阿里云容器服务差异化 SLO 混部技术实践
阿里巴巴在“差异化 SLO 混合部署”上已经有了多年的实践经验,目前已达到业界领先水平。所谓“差异化 SLO”,就是将不同类型的工作负载混合运行在同一节点,充分利用工作负载对资源 SLO 需求特征的不同,提升资源整体使用效率。本文将重点介绍相关技术细节和使用方法,让用户可以充分享受差异化 SLO 带来的技术红利。
阿里云容器服务差异化 SLO 混部技术实践
|
分布式计算 算法 大数据
|
IDE 开发工具 数据格式
【最新技术早知道】PCIe Gen5 还没用上,Gen6 就来了?PCIe 6.0 系列文章之:《PCIe 6.0,到底 6 在哪?》
【最新技术早知道】PCIe Gen5 还没用上,Gen6 就来了?PCIe 6.0 系列文章之:《PCIe 6.0,到底 6 在哪?》
2139 0
|
网络协议 网络安全 网络虚拟化
从 IPv4 向 IPv6 的迁移
如果没有明确的迁移方法的话,将无法实施一种新的路由协议,迁移过程越简单,就越可能实施新协议。IPv6 与 IPv4 之间的互动操作性是势在必行的,IPv6 节点需要与 IPv4 节点进行通信,至少在初始阶段是这样的,而且在互通时间上还可能非常不确定。NGTRANS IETF 工作制定了多种迁移方法来推动从 IPv4 向 ipv6 的迁移工作,并确保 IPv4 与 IPv6 之间的兼容性。
868 0
|
传感器 机器学习/深度学习 人工智能
AI专用领域之一:声音、相机陷阱用于野生动物研究和保护
在这篇文章中以两篇文章为基础,分别讨论了声音、相机陷阱(camera traps)是如何实现野生动物监测的。此外,最后一篇文章还讨论了如何利用人工智能技术辅助解决野生动物偷猎(wildlife poaching)的问题,即对偷猎者轨迹的预测问题。
521 0
AI专用领域之一:声音、相机陷阱用于野生动物研究和保护
|
Web App开发 开发者 Windows
Google浏览器Chrome,总是弹框提示The device was not found的解决办法
Google浏览器Chrome,总是弹框提示The device was not found的解决办法
1292 0
Google浏览器Chrome,总是弹框提示The device was not found的解决办法

热门文章

最新文章