計算1^1+2^2+3^3+4^4+5^5+……+20^20 ,大數運算(加,乘)java實現
阿新 • • 發佈:2019-02-10
這個題目是明顯的大數運算,不能直接使用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(); } }