这个题目是明显的大数运算,不能直接使用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();
}
}