Java 将数字转换为大写金额_java输出大写金额-程序员宅基地

技术标签: java  

在网上搜了半天,发现知乎的这篇回答里面的代码写的不错【Java将数字转换成人民币金额大写 - 时光和月云的文章 - 知乎】
但是这个回答里面的代码存在两个问题
1.整数部分和小数部分都可能会有多余的“零”
2.没法根据参数 动态处理多余的小数
于是对代码进行了重写,测试了一下应该没有问题(代码中的RoundingMode可以参考这篇博文)


import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

public class UppercaseNumberUtils {
    private final static String[] UPPERCASE_NUMBER = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
    private final static String[] UPPERCASE_POSITION_NUMBER = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿"};
    private final static String[] UPPERCASE_DECIMAL_NUMBER = {"", "角", "分"};

    /**
     * 根据price,返回对应的大写金额
     * 如果price有超过两位小数,则会根据RoundingMode处理多余的小数
     * 如果price 为null、为空或者为负数,则抛出IllegalArgumentException异常
     * 如果price无法转换为数字,则抛出NumberFormatException异常
     * 如果price 为0,则返回 零元
     */
    public static String format(String price, RoundingMode roundingMode) {
        //校验price参数,可以自行修改
        checkPrice(price);
        //如果是price是"0",则直接返回零元
        if ("0".equals(price)) {
            return "零元";
        }
        //处理超过两位的小数和多余的0
        BigDecimal priceBigDecimal = new BigDecimal(price);
        String formatPrice = priceBigDecimal.setScale(2, roundingMode)
                .stripTrailingZeros().toPlainString();
        //判断是否有小数
        if (formatPrice.contains(".")) {
            int dotIndex = formatPrice.indexOf(".");
            //获取小数点左边
            StringBuilder upperInt=getUpperInt(formatPrice.substring(0, dotIndex));
            //获取小数点右边
            StringBuilder decimal = getUpperDecimal(formatPrice.substring(dotIndex + 1));
            //有小数的整数部分加上元
            return upperInt.append("元").append(decimal).toString();
        } else {
            //整数需要加上元整
            return getUpperInt(formatPrice).append("元整").toString();
        }
    }

    /**
     * 校验price参数,可以自行修改
     */
    private static void checkPrice(String price) {
        if (Objects.isNull(price) || price.isEmpty()) {
            throw new IllegalArgumentException("price参数为null或者为空");
        }
        BigDecimal priceBigDecimal;
        try {
            priceBigDecimal = new BigDecimal(price);
        } catch (NumberFormatException exception) {
            throw new NumberFormatException("price参数无法被转换为数字,price:" + price);
        }
        if (priceBigDecimal.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("price参数小于0,price:" + price);
        }
    }



    /**
     *  获取小数点左边,包含正整数和0的,0来自0-1之间小数的小数点左边部分
     *  如果intStr 为"0",则返回”零“。
     */
    private static StringBuilder getUpperInt(String intStr) {
        if ("0".equals(intStr)){
            return new StringBuilder("零");
        }
        StringBuilder intSB = new StringBuilder();
        for (int i = 0; i < intStr.length(); i++) {
            intSB.append(UPPERCASE_NUMBER[intStr.charAt(i) - 48]); //按数组的编号加入对应大写汉字
        }
        int cpCursor = 1;
        for (int j = intStr.length() - 1; j > 0; j--) {
            intSB.insert(j, UPPERCASE_POSITION_NUMBER[cpCursor]);   //在j之后加字符,不影响j对原字符串的相对位置
            //只是intStr.length()不断增加
            //insert(j,"string")就在j位置处插入,j=0时为第一位
            cpCursor = cpCursor == 8 ? 1 : cpCursor + 1;    //亿位之后重新循环
        }
        String zero = "零";
        while (intSB.indexOf("零拾") != -1) {  //当十位为零时用一个"零"代替"零拾"
            //replace的起始于终止位置
            intSB.replace(intSB.indexOf("零拾"), intSB.indexOf("零拾") + 2, zero);
        }
        while (intSB.indexOf("零佰") != -1) {  //当百位为零时,同理
            intSB.replace(intSB.indexOf("零佰"), intSB.indexOf("零佰") + 2, zero);
        }
        while (intSB.indexOf("零仟") != -1) {  //同理
            intSB.replace(intSB.indexOf("零仟"), intSB.indexOf("零仟") + 2, zero);
        }
        while (intSB.indexOf("零万") != -1) {  //万需保留,中文习惯
            intSB.replace(intSB.indexOf("零万"), intSB.indexOf("零万") + 2, "万");
        }
        while (intSB.indexOf("零亿") != -1) {  //同上
            intSB.replace(intSB.indexOf("零亿"), intSB.indexOf("零亿") + 2, "亿");
        }
        while (intSB.indexOf("零零") != -1) {//有连续数位出现零,则有以下情况,此时根据习惯保留一个零即可
            intSB.replace(intSB.indexOf("零零"), intSB.indexOf("零零") + 2, zero);
        }
        while (intSB.indexOf("亿万") != -1) {  //特殊情况,如:100000000,根据习惯保留高位
            intSB.replace(intSB.indexOf("亿万"), intSB.indexOf("亿万") + 2, "亿");
        }
        //由于已经处理过0,所以可以删除所有结尾的零
        while (intSB.lastIndexOf("零") == intSB.length() - 1) {
            intSB.delete(intSB.lastIndexOf("零"), intSB.lastIndexOf("零") + 1);
        }
        return intSB;
    }

    /**
     * 小数部分的处理
     */
    private static StringBuilder getUpperDecimal(String decimalStr) {
        StringBuilder decimal = new StringBuilder(decimalStr);
        //替换大写汉字
        for (int j = 0; j < decimal.length(); j++) {
            decimal.replace(j, j + 1, UPPERCASE_NUMBER[decimal.charAt(j) - 48]);
        }
        //插入中文标识
        for (int i = decimal.length(); i > 0; i--) {
            decimal.insert(i, UPPERCASE_DECIMAL_NUMBER[i]);
        }
        return decimal;
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_19934363/article/details/132120499

智能推荐

php laravel实战项目,Laravel框架应用:7个实战项目-程序员宅基地

文章浏览阅读1.4k次。很多PHP开发者在进行项目开发的时候,第一时间就会想到Laravel,如果你也正想学习这个优雅简洁的Laravel框架,不妨可以从以下8个教程入手,从基础到实战项目都包含了。Laravel框架简介:Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来,帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。..._laravel项目实例

consider using the '--user' option or check the permissions错误_consider using the `--user` option or check the pe-程序员宅基地

文章浏览阅读4.9w次,点赞23次,收藏37次。 win7下使用pip install numpy出现错误consider using the '--user' option or check the permissions纠正方法:pip install --user numpy参考链接:https://github.com/googlesamples/assistant-sdk-python/issues/244 ..._consider using the `--user` option or check the permissions.

就读体验丨香港科技大学工学院科技领导及创业(TLE)理学硕士学位课程(上)_technology leadership and entrepreneurship-程序员宅基地

文章浏览阅读3.3k次,点赞2次,收藏2次。本文转载自公众号:HKUSTGSAA项目概览香港科技大学工学院的Technology Leadership and Entrepreneurship(TLE)MSc program项目时长Full-time1.5年,Part-time 3年,学生必须修满至少30学分的课程才能毕业。其中包括9学分的核心课程,6学分的工程学院提供的技术类选修课,6学分的工商管理学院、工学院、理学院或公共政策学院提供的选修课,以及9个学分的 Project。TLE项目希望同学在项目期间初步完成自己的创业产品雏形,所以非.._technology leadership and entrepreneurship

毕设开源 基于协同过滤的电影推荐系统-程序员宅基地

文章浏览阅读780次,点赞28次,收藏26次。今天学长向大家介绍一个学长帮助往届学生做的毕业设计项目基于协同过滤的电影推荐系统选题指导, 项目分享:见文末**毕设帮助, 选题指导, 项目分享: **

解决hue窗口中文报错问题:1366, Incorrect string value:… for column search at row 1_(1366, "incorrect string value: '\\xe8' for column-程序员宅基地

文章浏览阅读612次。在hue中查询条件加了中文,或者有中文注释都会报错(1366, Incorrect string value:… for column search at row 1)修改hue元数据库的字符编码:alter database hue character set latin1;alter table beeswax_queryhistory modify `query` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;_(1366, "incorrect string value: '\\xe8' for column 'search' at row 1")

DL:RBM学习算法——Gibbs采样、变分方法、对比散度、模拟退火_gibbs采样和模拟退火-程序员宅基地

文章浏览阅读1.1w次,点赞4次,收藏24次。RBM学习方法当前在对RBM 的研究中,典型的学习方法有Gibbs 采样(Gibbs sampling)算法,变分近似方法(variational approach),对比散度(contrastive divergence,CD)算法,模拟退火(simulate annealing) 算法等。下面对这些方法进行对比。1、Gibbs采样算法(1)简介G_gibbs采样和模拟退火

随便推点

Hutool基本用法介绍-程序员宅基地

文章浏览阅读1.5k次。在使用过程中,可以查阅 Hutool 的官方文档或者源码,以便更好地了解每个工具的具体用法和参数。它提供了丰富的工具类和方法,涵盖了字符串处理、日期时间操作、网络请求、文件操作、加解密、数据校验、反射操作等领域。你可以根据自己的项目需求选择适合的工具,来简化你的 Java 开发过程。发起 HTTP 请求(GET、POST、PUT、DELETE 等),支持设置请求头、请求参数、响应处理等。提供文件复制、移动、删除、读取、写入等操作,还支持递归遍历文件夹。支持 XML 数据的解析、生成和操作。_hutool

基于autojs脚本语言引擎开发的安卓ipv6聊天室开源了,全网独家-程序员宅基地

文章浏览阅读1.3k次。说明本文提供的代码仅供参考。可能有些地方在最新版本的Auto.js上面需要做修改,才能运行。Auto.js简介Auto.js是利用安卓系统的“辅助功能”实现类似于按键精灵一样,可以通过代码模拟一系列界面动作的辅助工作。与“按键精灵”不同的是,它的模拟动作并不是简单的使用在界面定坐标点来实现,而是类似与win一般,找窗口句柄来实现的。Auto.js使用JavaScript作为脚本语言,目...

MyBaits 批量插入Script脚本注解_mybatis script标签-程序员宅基地

文章浏览阅读1.4k次。mybatis中实现批量插入数据,我们可以使用脚本进行开发,还需要用到foreach标签代码service层dao层@Insert("<script>" + "insert into book(category_id,name,level,price,img_path,create_time," + "update_time) values" ........._mybatis script标签

select * 和select 1,select count(*)和select count(1)-程序员宅基地

文章浏览阅读1.1w次,点赞13次,收藏82次。1、select * 和select 1的区别如果要返回数据,使用select * ,如果要判断有没有结果使用select 1;2、select count(*)和select count(1)的区别一般情况下,select count(*)和select count(1)两个返回的结果是一样的。_select 1

帮 C/C++ 程序员彻底了解链接器(转)-程序员宅基地

文章浏览阅读66次。转自:http://blog.jobbole.com/96225/本文旨在帮助 C/C++ 程序员们了解链接器到底完成了些什么工作。多年来,我给许多同事解释过这一原理,因此我觉得是时候把它写下来了,这样不仅可以供更多人学习,也省去我一遍遍讲解。[2009年3月更新,内容包括:增加了 Windows 系统中链接过程可能遇到的特殊问题,以及对某条定义规则的澄清。]促使我写下这篇文章的起因是..._各部分的命名:看看 c 文件中都包含了哪些内容

美化你的APP——从Toolbar开始_如何美化app-程序员宅基地

文章浏览阅读2.5w次,点赞10次,收藏38次。Toolbar是什么Toolbar是Google在Android 5.0中推出的一款替代ActionBar的View。ActionBar必须得作为Activity内容的一部分,而Toolbar可以放在任何层次。Toolbar比ActionBar支持更多的功能,从开始到终点,Toolbar包含下面可选的元素: - 一个导航按钮。 可以是一个向前的按钮、导航菜单按钮,等等。 - 一个logo图片_如何美化app