Java常用数字工具类 数字转汉字(1)
作者:龙轩 发布时间:2022-06-25 11:01:45
本人是从事互联网金融行业的,所以会接触到一些金融类的问题,常见的一种就是数字转汉字大小写的问题。所以抽空就写了一个小小的工具类,实现了数字转汉字、大数相加、相减、相乘的工具类,希望能帮助有需求的同行们。本篇就分享一下数字转化为汉字的思路吧。
数字转汉字的原理:
拆分:由于整数部分要加权值,而小数部分直接转换即可,所以首先要将数字拆分成整数+小数;
整数处理:按照我们的中国人的习惯,把数字格式化成4位一组,不足4位前面补0。每次处理4位,按位匹配数组中的汉字+权值。即按照数值找数字数组(num_lower 、num_upper )中对应位置的汉字,按照在4位中的偏移量在单位权值数组(unit_lower 、unit_upper )中找。比如21,转化4位为0021,前面的0不用管,2对应数字“二”,权值是“十”,1对应数字“一”,权值是“(个)”用空字符串代替。即得到“二十一”。每4位处理完后,还要整体对应一个权值,比如“万、亿、兆”等;
小数处理:小数部分直接按位对应汉字数组和权值即可。
废话了这么多,可能云里雾里的,看看具体代码吧:
//num 表示数字,lower表示小写,upper表示大写
private static final String[] num_lower = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
private static final String[] num_upper = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
//unit 表示单位权值,lower表示小写,upper表示大写
private static final String[] unit_lower = { "", "十", "百", "千" };
private static final String[] unit_upper = { "", "拾", "佰", "仟"};
private static final String[] unit_common = {"","万", "亿","兆","京","垓","秭","穰","沟","涧","正","载"};
//允许的格式
private static final List<String> promissTypes = Arrays.asList("INTEGER","INT","LONG","DECIMAL","FLOAT","DOUBLE","STRING","BYTE","TYPE","SHORT");
/**
* 数字转化为小写的汉字
*
* @param num 将要转化的数字
* @return
*/
public static String toChineseLower(Object num){
return format(num, num_lower, unit_lower);
}
/**
* 数字转化为大写的汉字
*
* @param num 将要转化的数字
* @return
*/
public static String toChineseUpper(Object num){
return format(num, num_upper, unit_upper);
}
/**
* 格式化数字
*
* @param num 原数字
* @param numArray 数字大小写数组
* @param unit 单位权值
* @return
*/
private static String format(Object num,String[] numArray,String[] unit){
if(!promissTypes.contains(num.getClass().getSimpleName().toUpperCase())){
throw new RuntimeException("不支持的格式类型");
}
//获取整数部分
String intnum = getInt(String.valueOf(num));
//获取小数部分
String decimal = getFraction(String.valueOf(num));
//格式化整数部分
String result = formatIntPart(intnum,numArray,unit);
if(!"".equals(decimal)){//小数部分不为空
//格式化小数
result += "点"+formatFractionalPart(decimal, numArray);
}
return result;
}
/**
* 格式化整数部分
*
* @param num 整数部分
* @param numArray 数字大小写数组
* @return
*/
private static String formatIntPart(String num,String[] numArray,String[] unit){
//按4位分割成不同的组(不足四位的前面补0)
Integer[] intnums = split2IntArray(num);
boolean zero = false;
StringBuffer sb = new StringBuffer();
for(int i=0;i<intnums.length;i++){
//格式化当前4位
String r = formatInt(intnums[i], numArray,unit);
if("".equals(r)){//
if((i+1)==intnums.length){
sb.append(numArray[0]);//结果中追加“零”
}else{
zero=true;
}
}else{//当前4位格式化结果不为空(即不为0)
if(zero || (i>0 && intnums[i]<1000)){//如果前4位为0,当前4位不为0
sb.append(numArray[0]);//结果中追加“零”
}
sb.append(r);
sb.append(unit_common[intnums.length-1-i]);//在结果中添加权值
zero=false;
}
}
return sb.toString();
}
/**
* 格式化小数部分
*
* @param decimal 小数部分
* @param numArray 数字大小写数组
* @return
*/
private static String formatFractionalPart(String decimal,String[] numArray) {
char[] val = String.valueOf(decimal).toCharArray();
int len = val.length;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
int n = Integer.valueOf(val[i] + "");
sb.append(numArray[n]);
}
return sb.toString();
}
拆分整数和小数的方法在这里:
/**
* 获取整数部分
*
* @param num
* @return
*/
private static String getInt(String num){
//检查格式
checkNum(num);
char[] val = String.valueOf(num).toCharArray();
StringBuffer sb = new StringBuffer();
int t , s = 0;
for (int i = 0; i < val.length; i++) {
if(val[i]=='.') {
break;
}
t = Integer.parseInt(val[i]+"",16);
if(s+t==0){
continue;
}
sb.append(t);
s+=t;
}
return (sb.length()==0? "0":sb.toString());
}
/**
* 获取小数部分
*
* @param num
* @return
*/
private static String getFraction(String num){
int i = num.lastIndexOf(".");
if(num.indexOf(".") != i){
throw new RuntimeException("数字格式不正确,最多只能有一位小数点!");
}
String fraction ="";
if(i>=0){
fraction = getInt(new StringBuffer(num).reverse().toString());
if(fraction.equals("0")){
return "";
}
}
return new StringBuffer(fraction).reverse().toString();
}
/**
* 检查数字格式
*
* @param num
*/
private static void checkNum(String num) {
if(num.indexOf(".") != num.lastIndexOf(".")){
throw new RuntimeException("数字["+num+"]格式不正确!");
}
if(num.indexOf("-") != num.lastIndexOf("-") || num.lastIndexOf("-")>0){
throw new RuntimeException("数字["+num+"]格式不正确!");
}
if(num.indexOf("+") != num.lastIndexOf("+")){
throw new RuntimeException("数字["+num+"]格式不正确!");
}
if(num.indexOf("+") != num.lastIndexOf("+")){
throw new RuntimeException("数字["+num+"]格式不正确!");
}
if(num.replaceAll("[\\d|\\.|\\-|\\+]", "").length()>0){
throw new RuntimeException("数字["+num+"]格式不正确!");
}
}
通过这种分而治之的思路,处理起来就简单多了。写个main函数调用一下:
public static void main(String[] args) {
short s = 10;
byte b=10;
char c='A';
Object[] nums = {s, b, c, 0, 1001, 100100001L, 21., 205.23F, 205.23D, "01000010", "1000000100105.0123", ".142", "20.00", "1..2", true};
System.out.println("将任意数字转化为汉字(包括整数、小数以及各种类型的数字)");
System.out.println("--------------------------------------------");
for(Object num :nums){
try{
System.out.print("["+num.getClass().getSimpleName()+"]"+num);
for(int i=0;i<25-String.valueOf(num+num.getClass().getSimpleName()).length();i+=4){
System.out.print("\t");
}
//调用转化为小写和大写
System.out.print(" format:"+toChineseLower(num));
System.out.println("【"+toChineseUpper(num)+"】");
}catch(Exception e){
System.out.println(" 错误信息:"+e.getMessage());
}
}
}
看看结果吧:
从上述代码和运行结果中,我们可以看到该功能支持多种数据类型的转换、支持转化为一般汉字和财务专用大写汉字。还可以智能处理非正常逻辑的数字。比如“20”会转化为“二十”而非“二十零”;“1 0000 0001” 转换成“一亿零一”而非“一亿零万零一”。
这里只分享了一个转换汉字的功能,下篇将分享一下大数相乘、相加、相减的方法。支持小数和负数的运算,敬请期待。
来源:http://blog.csdn.net/xiaoxian8023/article/details/49834589
猜你喜欢
- 前言:mybatisplus 可以说是对mybatis更好的拓展,一些简单的增删改查的操作已经被作者实现,我们只需引用即可。1.数据库建表这
- 博主在初学注解的时候看到网上的介绍大部分都是直接介绍用法或者功能,没有实际的应用场景,篇幅又很长导致学习的时候难以理解其意图,而且学完就忘Q
- SpringBoot2之PUT请求接收不了参数的解决办法,这个问题,关乎两个Filter过滤器,是spring3和3.5之后提供的,目的就是
- 代码如下:try { // 创建一个线程 Thread thread = new Thread() {
- 本文实例为大家分享了JavaMail实现带附件的邮件发送的具体代码,供大家参考,具体内容如下发送纯文本的邮件package com.haiw
- 这篇文章主要介绍了Java编码摘要算法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参
- springcloud-gateway集成knife4j环境信息环境信息spring-boot:2.6.3spring-cloud-alib
- 1.线程池Executors的简单使用1)创建一个线程的线程池。 Executors.newSingleThreadExecutor();
- SpringBoot分离打Jar包的两种方式方式一:基于maven-jar-plugin此方式基于这个小伙伴的配置改的:https://ww
- public/protected/privatepublic表示公开,private表示私有,protected表示保护,什么都不写表示默认
- 前言在RequestMappingHandlerAdapter对request进行了适配,并且调用了目标handler之后,其会返回一个Mo
- 序列化一般应用与以下场景之中:1.永久性保存对象,把对象通过序列化字节流保存到本地文件中;2.通过序列化在网络中传输对象3.通过序列化在进程
- 一、研究背景在我们实际的项目开发中,我们会经常对文件进行相关任务的操作,具体的开发环节中,免不了让我们获取文件的后缀名,通过后缀名来进行下一
- Java 使用IO流实现大文件的分割与合并文件分割应该算一个比较实用的功能,举例子说明吧比如说:你有一个3G的文件要从一台电脑Copy到另一
- 这是之前软工课设我写的java访问mysql工具类,它经过了多轮的测试,应该能够适应大多数的操作需求。比之前大二写的更鲁棒,更易用。pack
- 核心考点:链表操作,临界条件检查,特殊情况处理在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针
- 所谓文件的断点续传,就是一个线程传输文件,另一个线程控制传输标识,以达到暂停文件效果、恢复文件上传的效果。本demo使用最基本的线程之间的通
- 最近项目中要做一个带进度条的上传文件的功能,学习了AsyncTask,使用起来比较方便,将几个方法实现就行,另外做了一个很简单的demo,希
- 主要从以下十几个方面对Hibernate做总结,包括Hibernate的检索方式,Hibernate中对象的状态,Hibernate的3种检
- 由于要做一个新项目,所以打算做一个简单的图片验证码。先说说思路吧:在服务端,从一个文件夹里面找出8张图片,再把8张图片合并成一张大图,在8个