求1到1000階乘之和
今天在脈脈的匿名區看到一個這個面試題,有個面試官說面試者連這道題都不會寫,我想了幾分鐘就能解出來,把代碼寫下來。寫得有點繁瑣了~~~,有高手可以指導更簡單的方法了麼。。。
求一個簡單的階乘很簡單,難的是當到後面結算的結果超過int 或者超過bigint的範圍的時候 ,數值就會錯誤。
核心的思想就是把簡單的階乘和變成大數的加法和乘法
import java.util.LinkedList;
import java.util.Queue;
public class BigNumerber {
/**
* @param args
* @author [email protected]
* @time 20160603 22:17
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//求1!+2!+3!+....+1000!
//求1到1000階乘之和,解法很簡單,就是把小數的乘法和加法變成大數的加法和乘法
String a="1";
String s="0";
for(int i=1;i<=1000;i++)
{
a=bigNumberMultiply(a,String.valueOf(i));
s=bigNumberAdd(s,a);
}
System.out.println(s);
}
public static String bigNumberAdd(String addend,String augend){
//大數的加法很簡單,多一個進位就行了,因爲最大的數是9+9=18,
int carry = 0;//進位
int len_add = 0;
int len_agd = 0;
int bigcount = 0;
int smallcount = 0;
int r,d,sum = 0;
final String number = "0123456789";
StringBuffer s_buf = new StringBuffer();
String longstr = null;
String s = null;
if(addend != null && augend != null){
len_add = addend.length();
len_agd = augend.length();
bigcount = len_add > len_agd ? len_add : len_agd;
smallcount = len_add < len_agd ? len_add : len_agd;
longstr = len_add > len_agd ? addend: augend;
}else{
return "-1";
}
for(int i = 0 ;i<bigcount ;i++){
if(i < smallcount){
if((number.indexOf(addend.charAt(len_add - i -1)) != -1 )&&(number.indexOf(augend.charAt(len_agd -i -1)) != -1)){
r = Integer.parseInt(String.valueOf(addend.charAt(len_add - i -1)));
d = Integer.parseInt(String.valueOf(augend.charAt(len_agd - i -1)));
sum = r + d + carry;//計算對應位數的值加之後的和
if (sum >= 10){//如果和大於等於10進一位
s = String.valueOf(sum);
carry = Integer.valueOf(s.substring(0, 1));
sum = Integer.valueOf(s.substring(1, 2));
}else{
carry = 0;
}
}else{
return "-1";
}
}else if(number.indexOf(longstr.charAt(bigcount - i -1)) != -1 ){
sum = Integer.parseInt(String.valueOf(longstr.charAt(bigcount - i -1))) + carry;
if (sum >= 10){
s = String.valueOf(sum);
carry = Integer.valueOf(s.substring(0, 1));
sum = Integer.valueOf(s.substring(1, 2));
}else{
carry = 0;
}
}
s_buf.append(sum);
}
if(carry > 0){
s_buf.append(carry);
carry=0;
}
return s_buf.reverse().toString();
}
public static String bigNumberMultiply(String multiplier ,String multiplicand){
//大數的乘法一樣,將每一位數字與另外一個個數相乘,再相加之後得到結果
Queue<String> queue = new LinkedList<String>();
int len_mpr,len_mpd,bigcount,smallcount,sum,last,d=0;
int carry = 0;
String s = null;
String longstr,shortstr= null;
final String number = "0123456789";
StringBuffer s_buf = new StringBuffer();
if(multiplier != null && multiplicand != null){
len_mpr = multiplier.length();
len_mpd = multiplicand.length();
bigcount = len_mpr > len_mpd ? len_mpr : len_mpd;
smallcount =len_mpr < len_mpd ? len_mpr : len_mpd;
longstr = len_mpr > len_mpd ? multiplier: multiplicand;
shortstr = longstr.equals(multiplicand)?multiplier:multiplicand;
}else{
return "-1";
}
for(int i=0;i < smallcount ;i++){
//將每個數進位與另外一個數相乘,放到一個鏈表裏面存在
if (number.indexOf(shortstr.charAt(smallcount - i - 1)) != -1) {
last = Integer.parseInt(String.valueOf(shortstr.charAt(smallcount - i - 1)));
for (int j = 0; j < bigcount; j++) {
if (Integer.parseInt(String.valueOf(longstr.charAt(bigcount- j - 1))) != -1) {
d = Integer.parseInt(String.valueOf(longstr.charAt(bigcount - j - 1)));
sum = last * d + carry;
if (sum >= 10) {
s = String.valueOf(sum);
carry = Integer.valueOf(s.substring(0, 1));
sum = Integer.valueOf(s.substring(1, 2));
} else {
carry = 0;
}
s_buf.append(sum);
} else {
return "-1";
}
}//j++
if(carry >0){
s_buf.append(carry);
carry = 0;
}
queue.offer(s_buf.reverse().toString());
s_buf.delete(0, s_buf.length());
}else{
return "-1";
}
}//i++
String res = "0";
int size = queue.size();
for(int k =queue.size();k > 0; k--){
//高位需要補0
StringBuffer num = new StringBuffer(queue.poll());
for(int l = 0;l<size -k;l++){
num.append("0");
}
res = bigNumberAdd(res,num.toString());
}
return res;
}
}