【解决方案 二十三】带单位的数值转大写人民币金额

简介: 【解决方案 二十三】带单位的数值转大写人民币金额

最近接到一个任务,要去把普通的数值带着单位转大写人民币金额,例如:5.2 万元 转为大写:伍万贰仟元,这其中可以拆解为两个任务,一个是数值转人民币大写,还有一个就是把单位体现进来,为了解耦合,我决定把逻辑分为两部分处理:

  • 只进行数值转大写人民币,不关心单位
  • 拿到数值后*单位,然后进行冗余0的去除,再调用数值转大写人民币方法

接下里就是实现过程:

MoneyConvert 全部代码实现类

package com.example.springboot.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
 * 金额转换
 */
public class MoneyConvert {
    /**
     * 整数部分单位
     */
    static String[] cashUnitLeft = {"元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万"};
    /**
     * 小数部分单位
     */
    static String[] cashUnitRight = {"角", "分", "厘"};
    /**
     * 大写数字
     */
    static String[] upperNumber = {"零", "壹", "贰", "弎", "肆", "伍", "陆", "柒", "捌", "玖"};
    /**
     * 移除所有BigDecimal的废弃补0
     *
     * @param money the money
     * @return the big decimal
     */
    public static BigDecimal removeAmtLastZero(BigDecimal money) {
        String strMoney = money.toString();
        if (strMoney.indexOf('.') != -1) {
            String[] arr = strMoney.split("\\.");
            String strDecimals = arr[1];
            List<String> list = new ArrayList<>();
            boolean isCanAdd = false;
            for (int i = strDecimals.length() - 1; i > -1; i--) {
                String ss = String.valueOf(strDecimals.charAt(i));
                if (!ss.equals("0")) {
                    isCanAdd = true;
                }
                if (!ss.equals("0") || isCanAdd) {
                    list.add(ss);
                }
            }
            StringBuilder strZero = new StringBuilder();
            for (int i = list.size() - 1; i > -1; i--) {
                strZero.append(list.get(i));
            }
            strMoney = String.format("%s.%s", arr[0], strZero);
        }
        return new BigDecimal(strMoney);
    }
    /**
     * 金额转换
     *
     * @param money the money
     * @return the string
     */
    public static String convert(BigDecimal money) {
        String moneyString = money.toString();
        try {
            if (moneyString.contains(".")) {                        //把数值分为整数型和带小数的数值分开处理。
                String left = moneyString.substring(0, moneyString.indexOf("."));
                String right = moneyString.substring(moneyString.indexOf(".") + 1);
                return convertLeft(left) + convertRight(right);
            } else {
                return convertLeft(moneyString);
            }
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
            System.out.println("请输入转换范围内现金");
            return null;
        }
    }
    /**
     * 整数部分金额转换
     *
     * @param left the money
     * @return the string
     */
    private static String convertLeft(String left) {
        //根据单位'亿','万','元',把整数部分分为3种情况处理
        int length = left.length();
        //金额在千元以内
        if (length <= 4) {
            //金额为'0'元时的特殊情况
            if (length == 1 && Integer.parseInt(left) == 0) {
                return "零元";
            }
            return convertPart(left, length);
        } else if (length <= 8) {
            //金额在千万元以内
            String part1 = left.substring(0, length - 4);
            String part2 = left.substring(length - 4, length);
            String result1 = convertPart(part1, length);
            String result2 = convertPart(part2, 4);
            return result1 + result2;
        } else if (length <= 12) {
            //金额在千亿元以内
            String part1 = left.substring(0, length - 8);            //截取单位为'亿'部分数值。
            String part2 = left.substring(length - 8, length - 4);    //截取单位为'万'部分数值。
            String part3 = left.substring(length - 4, length);        //截取单位为'元'部分数值。
            String result1 = convertPart(part1, length);            //转换单位为'亿'部分数值。
            String result2 = convertPart(part2, 8);                    //转换单位为'万'部分数值。
            String result3 = convertPart(part3, 4);                    //转换单位为'元'部分数值。
            String result = result1 + result2 + result3;
            return result;
        } else {
            throw new IllegalArgumentException("超出转换数值范围!");
        }
    }
    /**
     * 小部分金额转换
     *
     * @param right the money
     * @return the string
     */
    private static String convertRight(String right) {
        String result = "";
        for (int i = 0; i < right.length(); i++) {
            String detail = right.substring(i, i + 1);
            int value = Integer.parseInt(detail);
            String number = upperNumber[value];
            String unit = cashUnitRight[i];
            result = result.concat(number).concat(unit);
        }
        result = result.replaceAll("零角", "").replaceAll("零分", "").replaceAll("零厘", "");
        return result;
    }
    /**
     * 具体金额转换
     *
     * @param part     the money
     * @param position the money
     * @return the string
     */
    private static String convertPart(String part, int position) {
        String result = "";
        //用于排除单位为'万'时,四位数值均为'0'的情况
        if (part.equals("0000") && position == 8) {
            return "";
        }
        for (int i = 0; i < part.length(); i++) {
            int value = Integer.parseInt(String.valueOf(part.charAt(i)));
            String number = upperNumber[value];
            String unit = cashUnitLeft[position - 1 - i];
            result = result.concat(number).concat(unit);
        }
        //把单位'亿','万','元'放到最后替换
        result = result.replaceAll("零仟", "零").replaceAll("零佰", "零")
                .replaceAll("零拾", "零").replaceAll("零零", "零")
                .replaceAll("零零", "零").replaceAll("零亿", "亿")
                .replaceAll("零万", "万").replaceAll("零元", "元");
        return result;
    }
}

单元测试,测试金额转写

package com.example.springboot;
import com.example.springboot.service.MoneyConvert;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
/**
 * * @Name MoneyConvertTest
 * * @Description
 * * @author tianmaolin
 * * @Date 2022/2/25
 */
@SpringBootTest
public class MoneyConvertTest {
    @Test
    public void moneyConvertTest() {
        //1 准备数据,金额值以及金额单位,金额单位为万时,值为10000
        BigDecimal money_one = new BigDecimal("0.2343678");
        BigDecimal money_two = new BigDecimal("5.2");
        BigDecimal money_three = new BigDecimal("500.00000");
        BigDecimal unit = new BigDecimal("10000");
        //2 数字转大写人民币前进行预处理
        System.out.println("Before convert:" + money_one + "," + money_two + "," + money_three);
        System.out.println("Before convert with unit:" + money_one.multiply(unit) + "," + money_two.multiply(unit) + "," + money_three.multiply(unit));
        System.out.println("Before convert with unit remove 0:" + MoneyConvert.removeAmtLastZero(money_one.multiply(unit)) + "," + MoneyConvert.removeAmtLastZero(money_two.multiply(unit)) + "," + MoneyConvert.removeAmtLastZero(money_three.multiply(unit)));
        //2 金额转写逻辑
        String result_one = MoneyConvert.convert(MoneyConvert.removeAmtLastZero(money_one.multiply(unit)));
        String result_two = MoneyConvert.convert(MoneyConvert.removeAmtLastZero(money_two.multiply(unit)));
        String result_three = MoneyConvert.convert(MoneyConvert.removeAmtLastZero(money_three.multiply(unit)));
        System.out.println("After convert result_one:" + result_one);
        System.out.println("After convert result_two:" + result_two);
        System.out.println("After convert result_three:" + result_three);
    }
}

测试结果如下

Before convert:0.2343678,5.2,500.00000
Before convert with unit:2343.6780000,52000.0,5000000.00000
Before convert with unit remove 0:2343.678,52000,5000000
After convert result_one:贰仟弎佰肆拾弎元陆角柒分捌厘
After convert result_two:伍万贰仟元
After convert result_three:伍佰万元


相关文章
|
11月前
|
存储 算法 生物认证
matlab实现指纹识别
指纹识别技术凭借其唯一性和稳定性,已成为生物特征识别领域的重要组成部分。MATLAB作为强大的数值计算和图像处理平台,为指纹识别算法的研究与实现提供了有力支持。
|
11月前
|
人工智能 定位技术
千问APP来咯!会聊天,能办事,还免费!!
千问APP公测上线!基于全新Qwen3模型,打造全能AI助手,覆盖办公、地图、健康、购物等多场景,免费畅享智能聊天与办事体验。即刻下载,让AI成为你的日常伙伴。
7892 3
|
7月前
|
存储 JSON 安全
接口安全:签名、加密、防重放架构方案
本文详解接口安全三大核心防线:签名(防篡改/伪造)、加密(防窃听/泄露)、防重放(防复用攻击)。厘清三者边界与协同逻辑,提供生产级规范、主流算法选型及完整Java代码实现,助开发者构建真正安全的全链路接口防护体系。
1073 2
|
12月前
|
存储
二叉树搜索树插入,查找,删除,Key/Value二叉搜索树场景应用+源码实现
二叉搜索树(BST)是一种有序二叉树,左子树节点值小于根,右子树大于根。支持插入、查找、删除操作,平均时间复杂度为O(log n)。通过中序遍历可得有序序列。常用于实现字典、统计频次等场景,结合键值对(KV)结构可扩展应用。
|
存储 缓存 Linux
【实战指南】嵌入式RPC框架设计实践:六大核心类构建高效RPC框架
在先前的文章基础上,本文讨论如何通过分层封装提升一个针对嵌入式Linux的RPC框架的易用性。设计包括自动服务注册、高性能通信、泛型序列化和简洁API。框架分为6个关键类:BindingHub、SharedRingBuffer、Parcel、Binder、IBinder和BindInterface。BindingHub负责服务注册,SharedRingBuffer实现高效数据传输,Parcel处理序列化,而Binder和IBinder分别用于服务端和客户端交互。BindInterface提供简单的初始化接口,简化应用集成。测试案例展示了客户端和服务端的交互,验证了RPC功能的有效性。
999 105
|
存储 数据采集 JSON
供应链管理优化:通过京东API实现库存自动预警
通过京东API实现库存自动预警,可实时监控库存变化,结合销售、采购数据动态设置预警规则,优化库存周转效率,降低缺货风险与仓储成本,提升供应链管理自动化水平。
|
存储 区块链 数据安全/隐私保护
Uniswap丨justswap丨pancakeswap去中心化薄饼交易所系统开发逻辑分析及源码示例
Uniswap、JustSwap、PancakeSwap均为去中心化交易所,采用自动做市商(AMM)机制。Uniswap基于以太坊,通过Router、Factory和Pair合约实现交易功能;JustSwap基于TRON网络,支持TRC20代币交易,无手续费;PancakeSwap基于Binance Smart Chain,功能类似Uniswap,支持BSC代币交易。
|
存储 弹性计算 数据管理
阿里云对象存储OSS收费标准:存储、流量和请求等多个计费项详解
阿里云对象存储OSS提供多样化的计费模式,涵盖存储、流量、请求等多项费用。存储费用方面,按量付费标准型为0.09元/GB/月,包年包月则有9元40GB等多种选择。流量费用仅对公网出方向收费,价格区间从0.25至0.50元/GB不等,支持按量付费与流量包抵扣两种方式。更多详情及精准报价,欢迎访问阿里云OSS官方页面。
8229 1
|
人工智能 API 数据库
FastGPT一站式解决方案[1-部署篇]:轻松实现RAG-智能问答系统(含sealos云端部署、docker部署、OneAPI&Xinference模型接入)
【9月更文挑战第5天】 FastGPT一站式解决方案[1-部署篇]:轻松实现RAG-智能问答系统(含sealos云端部署、docker部署、OneAPI&Xinference模型接入)
 FastGPT一站式解决方案[1-部署篇]:轻松实现RAG-智能问答系统(含sealos云端部署、docker部署、OneAPI&Xinference模型接入)
|
数据挖掘 物联网 API
API接口在各个领域的发挥着什么样的作用呢
API接口在电商、金融、医疗、物联网、媒体和游戏等领域发挥重要作用。从商品管理、支付集成、用户管理,到金融风控、医疗数据共享、智能交通,再到内容整合、数据分析和游戏数据交互,API助力各行业实现高效协同与创新。

热门文章

最新文章