本人是从事互联网金融行业的,所以会接触到一些金融类的问题,常见的一种就是数字转汉字大小写的问题。所以抽空就写了一个小小的工具类,实现了数字转汉字、大数相加、相减、相乘的工具类,希望能帮助有需求的同行们。本篇就分享一下数字转化为汉字的思路吧。
数字转汉字的原理:
- 拆分:由于整数部分要加权值,而小数部分直接转换即可,所以首先要将数字拆分成整数+小数;
- 整数处理:按照我们的中国人的习惯,把数字格式化成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+"]格式不正确!");
- }
- }
- 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” 转换成“一亿零一”而非“一亿零万零一”。
这里只分享了一个转换汉字的功能,下篇将分享一下大数相乘、相加、相减的方法。支持小数和负数的运算,敬请期待。
完整代码:
/** * 数字转汉字工具类 * * @author arron * @date 2015年7月21日 下午4:14:16 * @version 1.0 */ public class NumUtils { //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"); //标记为小数点 private static final int DOT=-99; //标记为无效数字 private static final int INVALID=-100; /** * 数字转化为小写的汉字 * * @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 * @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 */ 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+"]格式不正确!"); } } /** * 获取小数部分 * * @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(); } /** * 分割数字,每4位一组 * * @param num * @return */ private static Integer[] split2IntArray(String num){ String prev = num.substring(0,num.length() % 4); String stuff = num.substring(num.length() % 4); if(!"".equals(prev)){ num = String.format("%04d",Integer.valueOf(prev))+stuff; } Integer[] ints = new Integer[num.length()/4]; int idx=0; for(int i=0;i<num.length();i+=4){ String n = num.substring(i,i+4); ints[idx++]=Integer.valueOf(n); } return ints; } /** * 格式化整数部分 * * @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(); } /** * 格式化4位整数 * * @param num * @param numArray * @return */ private static String formatInt(int num,String[] numArray,String[] unit){ char[] val = String.valueOf(num).toCharArray(); int len = val.length; StringBuilder sb = new StringBuilder(); boolean isZero = false; for (int i = 0; i < len; i++) { int n = Integer.valueOf(val[i] + "");//获取当前位的数值 if (n==0) { isZero = true; } else { if (isZero) { sb.append(numArray[Integer.valueOf(val[i-1] + "")]); } sb.append(numArray[n]); sb.append(unit[(len - 1) - i]); isZero=false; } } return sb.toString(); } 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()); } } } }
转自:https://blog.csdn.net/xiaoxian8023/article/details/49834589
相关推荐
总结而言,“对比工具文件夹,java代码等”这一主题涵盖了使用文件对比工具——如Beyond Compare——进行文件和文件夹比较的基本概念,以及在Java开发中的应用。同时,我们也了解到如何处理软件授权问题,以及如何...
《Pinyin4j工具包详解:汉字转拼音的利器》 在处理中文数据时,我们经常需要将汉字转换为拼音,以便进行各种处理,如排序、搜索或建立索引。这时,一个强大的工具包——net.sourceforge.pinyin4j就显得尤为重要。这...
总之,pinyin4j 2.5.0版本是一个强大而稳定的中文转拼音工具,它为Java开发者提供了便利,极大地简化了处理中文字符的复杂性。通过熟练掌握pinyin4j的使用,我们可以更好地应对中文信息处理的挑战,提升项目的技术...
1. **代码浏览器**:Understand提供了一个直观的代码浏览器,支持多种编程语言,包括C、C++、Java、Python等,可以查看类、函数、变量等定义,以及它们之间的关系。 2. **代码结构分析**:通过构建代码的抽象语法树...
总的来说,“pingyin4j-2.5.0rar”是一个强大的工具,为Java开发者处理中文字符排序问题提供了便利。通过这个库,我们可以轻松实现基于拼音的中文数据排序,提升用户体验,同时减少了开发和维护的工作量。对于任何...
总的来说,对日编程的利器——强大的即时翻译软件,是提高跨语言开发效率的关键工具。它们通过屏幕取词、多语言支持和便捷的集成方式,帮助开发者轻松跨越语言障碍,使得即使是对日语不熟悉的人也能高效地进行对日...
《精通JS脚本之ExtJS框架》由浅入深地讲解了ExtJS在Web开发中的相关技术。本书共分17章,分别介绍了JavaScript的对象编程、JavaScript浏览器对象模型和事件机制、ExtJS的核心类库和组件、ExtJS的事件处理方式、设计...
《精通JS脚本之ExtJS框架》由浅入深地讲解了ExtJS在Web开发中的相关技术。本书共分17章,分别介绍了JavaScript的对象编程、JavaScript浏览器对象模型和事件机制、ExtJS的核心类库和组件、ExtJS的事件处理方式、设计...
还有一个辅助工具Notepad++,这是一个功能强大的文本编辑软件,可以在指定文件夹中搜索字符串,对于在不在资源文件中的词条汉化,用这个可以极大减少工作量。 下载地址:………… 安装的步骤很简单了,下载上面三个...