数字工具类
package com.arronlong.common.util.num;import java.util.Arrays;
import java.util.List;/*** 數(shù)字轉(zhuǎn)漢字工具類(lèi)* * @author hubi* @date 2095年17月21日 下午29:14:16 * @version 1.0*/
public class NumUtils {//num 表示數(shù)字,lower表示小寫(xiě),upper表示大寫(xiě)private static final String[] num_lower = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };private static final String[] num_upper = { "零", "壹", "貳", "叁", "肆", "伍", "陸", "柒", "捌", "玖" };//unit 表示單位權(quán)值,lower表示小寫(xiě),upper表示大寫(xiě)private static final String[] unit_lower = { "", "十", "百", "千" };private static final String[] unit_upper = { "", "拾", "佰", "仟"};private static final String[] unit_common = {"","萬(wàn)", "億","兆","京","垓","秭","穰","溝","澗","正","載"};//允許的格式private static final List<String> promissTypes = Arrays.asList("INTEGER","INT","LONG","DECIMAL","FLOAT","DOUBLE","STRING","BYTE","TYPE","SHORT");//標(biāo)記為小數(shù)點(diǎn)private static final int DOT=-99;//標(biāo)記為無(wú)效數(shù)字private static final int INVALID=-100;/*** 數(shù)字轉(zhuǎn)化為小寫(xiě)的漢字* * @param num 將要轉(zhuǎn)化的數(shù)字* @return*/public static String toChineseLower(Object num){return format(num, num_lower, unit_lower);}/*** 數(shù)字轉(zhuǎn)化為大寫(xiě)的漢字* * @param num 將要轉(zhuǎn)化的數(shù)字* @return*/public static String toChineseUpper(Object num){return format(num, num_upper, unit_upper);}/*** 大數(shù)加法* * @param a 第一個(gè)數(shù)* @param b 第二個(gè)數(shù)* @return 最終結(jié)果*/public static String add(String a, String b){//檢查數(shù)字格式checkNum(a);checkNum(b);//標(biāo)記最終結(jié)果是否為負(fù)值boolean minus=false;//判斷是否有帶著-號(hào)if(a.startsWith("-") || b.startsWith("-")){//判斷是否全帶著-號(hào)if(a.startsWith("-") && b.startsWith("-")){//2個(gè)都帶著-號(hào),結(jié)果肯定為負(fù)值minus=true;if(a.startsWith("-")){a = a.substring(1);}if(b.startsWith("-")){b = b.substring(1);}}else{//如果只有一個(gè)是負(fù)值,則調(diào)用減法來(lái)完成操作if(a.startsWith("-")){//a是負(fù)數(shù)a = a.substring(1);return subduct(b, a);}else{b = b.substring(1);return subduct(a, b);}}}//獲取a,b的整數(shù)和小數(shù)部分String a_int = getInt(a);String a_fraction = getFraction(a);String b_int = getInt(b);String b_fraction = getFraction(b);//計(jì)算小數(shù)部分最大長(zhǎng)度int len_fraction = Math.max(a_fraction.length(), b_fraction.length());//計(jì)算整數(shù)部分最大長(zhǎng)度int len_int = Math.max(a_int.length(), b_int.length())+1;//a,b兩個(gè)數(shù)整數(shù)最大長(zhǎng)度和小數(shù)最大長(zhǎng)度之和+小數(shù)點(diǎn)(1位)int len = len_fraction + len_int+1;//創(chuàng)建結(jié)果數(shù)組int[] result = new int[len];//默認(rèn)全為0//為了方便計(jì)算,去掉小數(shù)點(diǎn)(最后在結(jié)果中加上小數(shù)點(diǎn))//將【整數(shù)部分】高低位對(duì)調(diào)(反轉(zhuǎn)是為了低位對(duì)齊),最終轉(zhuǎn)化為char數(shù)組//小數(shù)部分不用調(diào)整char[] s_a_int = reverseStr(a_int);char[] s_b_int = reverseStr(b_int);char[] s_a_fraction = a_fraction.toCharArray();char[] s_b_fraction = b_fraction.toCharArray();//采用整數(shù)+整數(shù),小數(shù)+小數(shù)的方式運(yùn)算add(s_a_int, s_b_int, len_fraction, result);add(s_a_fraction, s_b_fraction, 1-len_fraction, result);// 處理結(jié)果集合,如果是大于10的就向前一位進(jìn)位,本身進(jìn)行除10取余accumulateResultArrays(result);//標(biāo)記小數(shù)點(diǎn)位置markDot(len_fraction, result);//切掉無(wú)用的0cutUnusedZero(len_fraction, result);//然后將數(shù)據(jù)反轉(zhuǎn)return (minus ? "-" : "")+reverseResult(result);}/*** 大數(shù)減法* * @param a 第一個(gè)數(shù)* @param b 第二個(gè)數(shù)* @return 最終結(jié)果*/public static String subduct(String a, String b){//檢查數(shù)字格式checkNum(a);checkNum(b);//標(biāo)記最終結(jié)果是否為負(fù)值boolean minus=false;//判斷是否有帶著-號(hào)if(a.startsWith("-") || b.startsWith("-")){//判斷是否全帶著-號(hào)if(a.startsWith("-") && b.startsWith("-")){//2個(gè)都帶著-號(hào)if(a.startsWith("-")){a = a.substring(1);}if(b.startsWith("-")){b = b.substring(1);}return subduct(b, a);}else{//如果只有一個(gè)是負(fù)值,則調(diào)用加法來(lái)完成操作if(a.startsWith("-")){//a是負(fù)值,b是非負(fù)值return add(a, "-"+b);//2個(gè)負(fù)值的加法運(yùn)算}else{//b是負(fù)值b = b.substring(1);return add(a, b);//2個(gè)正值的加法運(yùn)算}}}//獲取a,b的整數(shù)和小數(shù)部分String a_int = getInt(a);String a_fraction = getFraction(a);String b_int = getInt(b);String b_fraction = getFraction(b);boolean isSame = false;//判斷大小if(b_int.length()>a_int.length()){//如果b>areturn "-"+subduct(b, a);}else if(b_int.length()==a_int.length()){char[] s_a = a_int.toCharArray();char[] s_b = b_int.toCharArray();for (int i = 0; i < s_a.length; i++) {if(s_b[i]>s_a[i]){minus=true;isSame=false;break;}else if(s_b[i]<s_a[i]){isSame=false;break;}else{isSame = true;}}if(isSame){//整數(shù)部分全部相同,對(duì)比小數(shù)部分s_a = a_fraction.toCharArray();s_b = b_fraction.toCharArray();for (int i = 0; i < Math.min(s_a.length, s_b.length); i++) {if(s_b[i]>s_a[i]){minus=true;isSame=false;break;}else if(s_b[i]<s_a[i]){isSame=false;break;}else{isSame = true;}}if(isSame){//前部分全相同if(s_b.length>s_a.length){//前部分全相同,b小數(shù)位數(shù)多,則 b>areturn "-"+subduct(b, a);}else if(s_b.length == s_a.length){return "0";}}else if(minus){//如果b>areturn "-"+subduct(b, a);}}}//計(jì)算小數(shù)部分最大長(zhǎng)度int len_fraction = Math.max(a_fraction.length(), b_fraction.length());//計(jì)算整數(shù)部分最大長(zhǎng)度int len_int = Math.max(a_int.length(), b_int.length());//a,b兩個(gè)數(shù)整數(shù)最大長(zhǎng)度和小數(shù)最大長(zhǎng)度之和+小數(shù)點(diǎn)(1位)int len = len_fraction + len_int+1;//創(chuàng)建結(jié)果數(shù)組int[] result = new int[len];//默認(rèn)全為0//為了方便計(jì)算,去掉小數(shù)點(diǎn)(最后在結(jié)果中加上小數(shù)點(diǎn))//將【整數(shù)部分】高低位對(duì)調(diào)(反轉(zhuǎn)是為了低位對(duì)齊),最終轉(zhuǎn)化為char數(shù)組//小數(shù)部分不用調(diào)整char[] s_a_int = reverseStr(a_int);char[] s_b_int = reverseStr(b_int);char[] s_a_fraction = a_fraction.toCharArray();char[] s_b_fraction = b_fraction.toCharArray();//采用整數(shù)+整數(shù),小數(shù)+小數(shù)的方式運(yùn)算subduct(s_a_int, s_b_int, len_fraction, result);subduct(s_a_fraction, s_b_fraction, 1-len_fraction, result);// 處理結(jié)果集合,如果是大于10的就向前一位進(jìn)位,本身進(jìn)行除10取余subductResultArrays(result);//標(biāo)記小數(shù)點(diǎn)位置markDot(len_fraction, result);//切掉無(wú)用的0cutUnusedZero(len_fraction, result);//然后將數(shù)據(jù)反轉(zhuǎn)return (minus ? "-" : "")+reverseResult(result);}/*** 大數(shù)乘法* * @param a 第一個(gè)數(shù)* @param b 第二個(gè)數(shù)* @return 最終結(jié)果*/public static String multiply(String a, String b){//檢查數(shù)字格式checkNum(a);checkNum(b);//標(biāo)記最終結(jié)果是否為負(fù)值boolean minus=false;//判斷是否有帶著-號(hào)if(a.startsWith("-") || b.startsWith("-")){//判斷是否全帶著-號(hào)if(a.startsWith("-") && b.startsWith("-")){}else{//只有1個(gè)帶著-號(hào),則結(jié)果為負(fù)值minus=true;}if(a.startsWith("-")){a = a.substring(1);}if(b.startsWith("-")){b = b.substring(1);}}//獲取a,b的整數(shù)和小數(shù)部分String a_int = getInt(a);String a_fraction = getFraction(a);String b_int = getInt(b);String b_fraction = getFraction(b);//計(jì)算小數(shù)部分的總長(zhǎng)度int len_fraction = a_fraction.length() +b_fraction.length() ;//a,b兩個(gè)數(shù)乘積的最大位數(shù)不會(huì)超過(guò)總位數(shù)之和+小數(shù)點(diǎn)(1位)int len = len_fraction +a_int.length()+b_int.length()+1;//創(chuàng)建結(jié)果數(shù)組int[] result = new int[len];//默認(rèn)全為0//為了方便計(jì)算,去掉小數(shù)點(diǎn)(最后在結(jié)果中加上小數(shù)點(diǎn))//并將高低位對(duì)調(diào)(反轉(zhuǎn)是為了低位對(duì)齊),最終轉(zhuǎn)化為char數(shù)組char[] s_a_int = reverseStr(a_int);char[] s_a_fraction = reverseStr(a_fraction);char[] s_b_int = reverseStr(b_int);char[] s_b_fraction = reverseStr(b_fraction);//將a、b都拆分成整數(shù)+小數(shù),然后//采用(x1+x2)(y1+y2)=x1y1+x1y2+x2y1+x2y2公式,分別計(jì)算乘積multiply(s_a_int, s_b_int, len_fraction, result);multiply(s_a_int, s_b_fraction, (len_fraction-s_b_fraction.length), result);multiply(s_b_int, s_a_fraction, (len_fraction-s_a_fraction.length), result);multiply(s_a_fraction, s_b_fraction, 0, result);// 處理結(jié)果集合,如果是大于10的就向前一位進(jìn)位,本身進(jìn)行除10取余accumulateResultArrays(result);//標(biāo)記小數(shù)點(diǎn)位置markDot(len_fraction, result);//切掉無(wú)用的0cutUnusedZero(len_fraction, result);//然后將數(shù)據(jù)反轉(zhuǎn)return (minus?"-":"") + reverseResult(result);}/*** 反轉(zhuǎn)字符串,并轉(zhuǎn)化為數(shù)組* * @param s 原字符串* @return*/private static char[] reverseStr(String s) {return new StringBuffer(s).reverse().toString().toCharArray();}/*** 累加每一位,超過(guò)10則然后進(jìn)位* * @param result 結(jié)果數(shù)組*/private static void accumulateResultArrays(int[] result) {for (int i = 0; i < result.length; i++) {if (result[i] >= 10) {result[i + 1] += result[i] / 10;result[i] %= 10;}}}/*** 檢查每一位,小于0(不含標(biāo)記的小數(shù)點(diǎn)未和無(wú)效的0)則然后向高位借位。* * @param result 結(jié)果數(shù)組*/private static void subductResultArrays(int[] result) {for (int i = 0; i < result.length-1; i++) {if (result[i] < 0 && result[i]>DOT) {result[i + 1]--;result[i] += 10;}}}/*** 去掉不必要的0(包括整數(shù)最前面的和小數(shù)最后面的0)* * @param len_fraction 小數(shù)長(zhǎng)度* @param result 結(jié)果數(shù)組*/private static void cutUnusedZero(int len_fraction, int[] result) {//去掉小數(shù)部分不必要的0boolean flag_0_fraction = true;//標(biāo)記一直是0for (int i =0; i< len_fraction; i++) {if(flag_0_fraction && result[i]==0){result[i]=INVALID;//為0時(shí)標(biāo)記為無(wú)效}else{flag_0_fraction=false;break;}}//去掉整數(shù)部分的0boolean flag_0_int=true;for (int i =result.length-1; i > len_fraction || (len_fraction==0 && i==0); i--) {if(flag_0_int && result[i]==0){result[i]=INVALID;//為0時(shí)標(biāo)記為無(wú)效}else{flag_0_int=false;//遇到不為0時(shí),停止。break;}}if(flag_0_int){//整數(shù)部分全為0result[len_fraction+1]=0;if(flag_0_fraction){//同時(shí),小數(shù)部分也全為0result[len_fraction]=INVALID;//不需要小數(shù)點(diǎn)了,所以置為無(wú)效}}else{//整數(shù)部分不為0if(flag_0_fraction && len_fraction>0){//小數(shù)部分全為0result[len_fraction]=INVALID;//不需要小數(shù)點(diǎn)了,所以置為無(wú)效}}}/*** 反轉(zhuǎn)結(jié)果,替換小數(shù)點(diǎn),跳過(guò)無(wú)效的0* * @param result 結(jié)果數(shù)組* @return*/private static String reverseResult(int[] result) {//反轉(zhuǎn)StringBuffer sb = new StringBuffer();for (int i = result.length - 1; i >= 0; i--) {if(result[i]>INVALID){sb.append(result[i]==DOT ? "." : result[i]);}}return sb.toString();}/*** 標(biāo)記小數(shù)點(diǎn)位置* * @param len_fraction 小數(shù)長(zhǎng)度* @param result 結(jié)果數(shù)組(反轉(zhuǎn)的)*/private static void markDot(int len_fraction, int[] result) {if(len_fraction>0){//標(biāo)記小數(shù)點(diǎn)位置for (int i = result.length-1 ; i > len_fraction; i--) {result[i] = result[i-1];}result[len_fraction]=DOT;//標(biāo)記小數(shù)點(diǎn)位置}}/*** 計(jì)算2個(gè)數(shù)的每一位的乘積,放入到對(duì)應(yīng)的結(jié)果數(shù)組中(未進(jìn)位)* * @param a 第一個(gè)數(shù)* @param b 第二個(gè)數(shù)* @param start 開(kāi)始放入的偏移位置* @param result 結(jié)果數(shù)組*/private static void multiply(char[] a, char[] b, int start , int[] result){// 計(jì)算結(jié)果集合for (int i = 0; i < a.length; i++) {for (int j = 0; j < b.length; j++) {result[i + j + start] += (int) (a[i] - '0') * (int) (b[j] - '0');}}}/*** 計(jì)算2個(gè)數(shù)的每一位的和,放入到對(duì)應(yīng)的結(jié)果數(shù)組中(未進(jìn)位)* * @param a 第一個(gè)數(shù)* @param b 第二個(gè)數(shù)* @param start 開(kāi)始放入的偏移位置* @param result 結(jié)果數(shù)組*/private static void add(char[] a, char[] b, int start , int[] result){char[] c=null;//保證a是位數(shù)多的,如果b長(zhǎng)度大于a,則交換a,bif(b.length>a.length){c=a;a=b;b=c;}// 計(jì)算結(jié)果集合,a的位數(shù)>=b的位數(shù)int i = 0, j=0;for (; i < a.length && j< b.length; i++,j++) {result[Math.abs(i + start)] += (int) (a[i] - '0') + (int) (b[j] - '0');}//如果a沒(méi)有處理完畢,直接把a(bǔ)剩下的值賦值給結(jié)果數(shù)組即可for (; i < a.length; i++) {result[Math.abs(i + start)] += (int) (a[i] - '0');}if(c!=null){//如果交換過(guò),則再交換回來(lái)c=a;a=b;b=c;}c=null;}/*** 計(jì)算2個(gè)數(shù)的每一位的差,放入到對(duì)應(yīng)的結(jié)果數(shù)組中(未進(jìn)位)* * @param a 第一個(gè)數(shù)* @param b 第二個(gè)數(shù)* @param start 開(kāi)始放入的偏移位置* @param result 結(jié)果數(shù)組*/private static void subduct(char[] a, char[] b, int start , int[] result){// 計(jì)算結(jié)果集合,a的位數(shù)>=b的位數(shù)int i = 0, j=0;for (; i < a.length && j< b.length; i++,j++) {result[Math.abs(i + start)] +=((int) (a[i] - '0') - (int) (b[j] - '0'));}//如果a沒(méi)有處理完畢,直接把a(bǔ)剩下的值賦值給結(jié)果數(shù)組即可for (; i < a.length; i++) {result[Math.abs(i + start)] +=((int) (a[i] - '0'));}//如果a沒(méi)有處理完畢,直接把a(bǔ)剩下的值賦值給結(jié)果數(shù)組即可for (; i < b.length; i++) {result[Math.abs(i + start)] +=-((int) (b[i] - '0'));}}/*** 格式化數(shù)字* * @param num 原數(shù)字* @param numArray 數(shù)字大小寫(xiě)數(shù)組* @param unit 單位權(quán)值* @return*/private static String format(Object num,String[] numArray,String[] unit){if(!promissTypes.contains(num.getClass().getSimpleName().toUpperCase())){throw new RuntimeException("不支持的格式類(lèi)型");}//獲取整數(shù)部分String intnum = getInt(String.valueOf(num));//獲取小數(shù)部分String decimal = getFraction(String.valueOf(num));//格式化整數(shù)部分String result = formatIntPart(intnum,numArray,unit);if(!"".equals(decimal)){//小數(shù)部分不為空//格式化小數(shù)result += "點(diǎn)"+formatFractionalPart(decimal, numArray);}return result;}/*** 獲取整數(shù)部分* * @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());}/*** 檢查數(shù)字格式* * @param num*/private static void checkNum(String num) {if(num.indexOf(".") != num.lastIndexOf(".")){throw new RuntimeException("數(shù)字["+num+"]格式不正確!");}if(num.indexOf("-") != num.lastIndexOf("-") || num.lastIndexOf("-")>0){throw new RuntimeException("數(shù)字["+num+"]格式不正確!");}if(num.indexOf("+") != num.lastIndexOf("+")){throw new RuntimeException("數(shù)字["+num+"]格式不正確!");}if(num.indexOf("+") != num.lastIndexOf("+")){throw new RuntimeException("數(shù)字["+num+"]格式不正確!");}if(num.replaceAll("[\\d|\\.|\\-|\\+]", "").length()>0){throw new RuntimeException("數(shù)字["+num+"]格式不正確!");}}/*** 獲取小數(shù)部分* * @param num* @return*/private static String getFraction(String num){int i = num.lastIndexOf(".");if(num.indexOf(".") != i){throw new RuntimeException("數(shù)字格式不正確,最多只能有一位小數(shù)點(diǎn)!");}String fraction =""; if(i>=0){fraction = getInt(new StringBuffer(num).reverse().toString());if(fraction.equals("0")){return "";}}return new StringBuffer(fraction).reverse().toString();}/*** 分割數(shù)字,每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;}/*** 格式化整數(shù)部分* * @param num 整數(shù)部分* @param numArray 數(shù)字大小寫(xiě)數(shù)組* @return*/private static String formatIntPart(String num,String[] numArray,String[] unit){//按4位分割成不同的組(不足四位的前面補(bǔ)0)Integer[] intnums = split2IntArray(num);boolean zero = false;StringBuffer sb = new StringBuffer();for(int i=0;i<intnums.length;i++){//格式化當(dāng)前4位String r = formatInt(intnums[i], numArray,unit);if("".equals(r)){//if((i+1)==intnums.length){sb.append(numArray[0]);//結(jié)果中追加“零”}else{zero=true;}}else{//當(dāng)前4位格式化結(jié)果不為空(即不為0)if(zero || (i>0 && intnums[i]<1000)){//如果前4位為0,當(dāng)前4位不為0sb.append(numArray[0]);//結(jié)果中追加“零”}sb.append(r);sb.append(unit_common[intnums.length-1-i]);//在結(jié)果中添加權(quán)值zero=false;}}return sb.toString();}/*** 格式化小數(shù)部分* * @param decimal 小數(shù)部分* @param numArray 數(shù)字大小寫(xiě)數(shù)組* @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位整數(shù)* * @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] + "");//獲取當(dāng)前位的數(shù)值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("將任意數(shù)字轉(zhuǎn)化為漢字(包括整數(shù)、小數(shù)以及各種類(lèi)型的數(shù)字)");
// 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(" 錯(cuò)誤信息:"+e.getMessage());
// }
// }String a = "9213213210.4508";String b = "12323245512512100.4500081";String r = multiply(a, b);System.out.println(a+"*"+b+"="+r);String r1 = add(a, b);System.out.println(a+"+"+b+"="+r1);String r2 = subduct(a, b);System.out.println(a+"-"+b+"="+r2);}
}
總結(jié)
- 上一篇: VC 常见问题百问
- 下一篇: PTA 7-10 字符转换 (15分)