1. 程式人生 > >計算1^1+2^2+3^3+4^4+5^5+……+20^20 ,大數運算(加,乘)java實現

計算1^1+2^2+3^3+4^4+5^5+……+20^20 ,大數運算(加,乘)java實現

這個題目是明顯的大數運算,不能直接使用int long double 早就超出範圍了,要用陣列結合字串進行處理,分別實現大數的加法和乘法,

然後使用實現的加法和乘法寫出來n的n次冪的實現,最後 把它們加起來

首先存進來就是要用string來存貯,運算的時候按位運算,charAt(i)-'0'來取值。

注意一點,string改成char[]陣列的時候要變成反序操作,因為對於一個數組是要從左到右,相加放值的,所以我們也要從左向右操作,所以原數值要逆序存放,運算結束後,再逆序回來。

//計算1^1+2^2+3^3+4^4+5^5+……+20^20  
public class Main1 {  
  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
               
             String sum = "0";  
             //進行迴圈20次 從1的1次方 加到20的20次方  
               
            for(int i = 1;i<21;i++)  
            {  
                 sum = bigNumberAdd(sum, NCiOfN(i));  
            }  
            System.out.println(sum);  
    }  
  
     //這裡實現 n的n次冪  
    public static String NCiOfN(int n)  
    {  
        String result = "1";  
        String value = String.valueOf(n);  
        for(int i=0;i<n;i++)  
        {  
             result = bigNumberSimpleMulti(result,value);  
        }  
        return result;  
    }  
      
    //這裡用陣列實現大數的相乘運算  
    public static String bigNumberSimpleMulti(String f, String s) {    
       // System.out.print("乘法:\n" + f + "*" + s + "=");    
        // 獲取首字元,判斷是否是符號位    
        char signA = f.charAt(0);    
        char signB = s.charAt(0);    
        char sign = '+';    
        if (signA == '+' || signA == '-') {    
            sign = signA;    
            f = f.substring(1);    
        }    
        if (signB == '+' || signB == '-') {    
            if (sign == signB) {    
                sign = '+';    
            } else {    
                sign = '-';    
            }    
            s = s.substring(1);    
        }    
        // 將大數翻轉並轉換成字元陣列    
        char[] a = new StringBuffer(f).reverse().toString().toCharArray();    
        char[] b = new StringBuffer(s).reverse().toString().toCharArray();    
        int lenA = a.length;    
        int lenB = b.length;    
        // 計算最終的最大長度    
        int len = lenA + lenB;     //兩個數相乘之後的最大位數不會超過原來兩個數的長度之和,兩數相加之後的最大位數是,最長的原數長度+1,見下
        int[] result = new int[len];     //用一個int陣列按位存放結果(逆序的)
        // 計算結果集合    
        for (int i = 0; i < a.length; i++) {    
            for (int j = 0; j < b.length; j++) {    
                result[i + j] += (int) (a[i] - '0') * (int) (b[j] - '0');    //先將結果陣列中所有位直接求值,進位之後再處理    
            }    
        }    
        // 處理結果集合,如果是大於10的就向前一位進位,本身進行除10取餘    
        for (int i = 0; i < result.length; i++) {         //開始從頭開始處理每一位結果
            if (result[i] > 10) {    
                result[i + 1] += result[i] / 10;    //從0位開始,i+1位放入i的進位
                result[i] %= 10;    //i只保留餘數,這樣結果陣列肯定會繼續變長,沒關係就繼續這樣算就行,自己寫到不用再進位
            }    
        }    
        StringBuffer sb = new StringBuffer();    
        // 該欄位用於標識是否有前置0,如果是0就不需要列印或者儲存下來    
        boolean flag = true;    
        for (int i = len - 1; i >= 0; i--) {    
            if (result[i] == 0 && flag) {      //陣列後端的0有幾位
                continue;    
            } else {    
                flag = false;    
            }    
            sb.append(result[i]);    
        }    
        if (!sb.toString().equals("")) {    
            if (sign == '-') {    //最開始提取的正負號,直接加入到結果的開頭
                sb.insert(0, sign);    
            }    
        } else {    
            sb.append(0);    
        }    
        // 返回最終結果    
      //  System.out.println(sb.toString());    
        return sb.toString();  
    }    
   ////////////////////////////////////////////////////////////////////////////////////////////   
  //這裡實現大數的相加運算  
    public static String bigNumberAdd(String f, String s) {    
        //翻轉兩個字串,並轉換成陣列    
        char[] a = new StringBuffer(f).reverse().toString().toCharArray();    
        char[] b = new StringBuffer(s).reverse().toString().toCharArray();    
        int lenA = a.length;    
        int lenB = b.length;    
        //計算兩個長字串中的較長字串的長度    
        int len = lenA > lenB ? lenA : lenB;    //兩數相加之後的最大長度,為最長的元資料長度+1,區別於相乘
        int[] result = new int[len + 1];    
        for (int i = 0; i < len + 1; i++) {    //還是先正常算出每一位的,不帶進位操作的值
            //如果短的數到頭了,就用0代替,和另一個字元陣列中的數字相加    
            int aint = i < lenA ? (a[i] - '0') : 0;    
            int bint = i < lenB ? (b[i] - '0') : 0;    
            result[i] = aint + bint;    
        }    
        //處理結果集合,如果大於10的就向前一位進位,本身進行除10取餘    
        for (int i = 0; i < result.length; i++) {        //再從頭處理一遍進位的操作
            if (result[i] > 10) {    
                result[i + 1] += result[i] / 10;    
                result[i] %= 10;    
            }    
        }    
        StringBuffer sb = new StringBuffer();    
        //該欄位用於標識是否有前置0,如果有就不要儲存    
        boolean flag = true;    
        for (int i = len; i >= 0; i--) {    
            if (result[i] == 0 && flag) {    
                continue;    
            } else {    
                flag = false;    
            }    
            sb.append(result[i]);    
        }    
        return sb.toString();    
    }    
      
}