看《最强大脑》某期 中徳pk赛中 德国选手“次方哥” 秒算99的17次方,结果是34位数,当时非常震惊。他坦言心算分为记忆部分和运算部分,由于记忆部分出错,结果错了一位数,但不管是如何算出来的,就算是完全背出来的也挺厉害的,毕竟11~99的1~20次方(次方哥的秒出范围)也有89*20=1680中组合,并且有很多结果都有几十位,靠记忆的话不太容易。
一般的计算器输出a的n次幂的结果时多是用科学计数法表示的,可以运行微软系统自带的计算器calc.exe 。
例如2^1024=1.797693134862315907729305190789e+308
2^10240=3.5249714121083826571348148398003e+3082
2^102400=溢出
99^17=8.4294319338392688324856426786417e+33(次方哥将倒数最后的一个4记成了5)
99^20=8.1790693759723087088919866054434e+39
2015^1124=1.0119445978051020448707773176553e+3714
下面贴出源码:
package com.express;
import java.util.Date;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println(calc(,));
System.out.println(calc(,));
//System.out.println(calc(999999,11621));
//System.out.println(calc(2,102400));
}
/**
* 求 a的N次方(理论上a可以是long类型19位数,N只能是int类型10位数)
* 建议N最好是不超过6位数(N为6位数时执行时间有时会超过5秒)
* long 最大值是19位数,所以要保证数组中的每个数与基数a相乘时不能溢出,
* 所以数组中数的位数为17-aLength,数组的维数只能是int类型,十位数
* 注意:输出时1030%1000 的结果应该取030而不是30,即要取满d位
* 思路:
* 1.先分别计算数组中每个数乘上基数后的值
* 2.然后循环将低位的数产生的进位累加到高位,如果最高位后还有进位,
* 再对最高位的数进行d位分组
* @param a 基数
* @param N 次方数
* @return 字符串格式的计算结果
*/
public static String calc(long a,int N)
{
if(a==) return "1";
System.out.println("计算"+a+"的"+N+"次幂:");
long startTime = new Date().getTime();
int aLengh = Long.toString(a).length();
//17的含义:
//如果基数是5位数乘以12位数最大是17位数,加上进位后最多18位数,
//不会超出long类型19位数,故取17保险
//在每次计算时是用基数a分别乘上数组中的每个数
int d = -aLengh;//数组中每个数的位数
int maxDim = aLengh*N/d+;//数组最大维数,为了防止越界溢出+2
System.out.println("数组每个数的位数="+d+",最大数组维数="+maxDim+
",最高共"+aLengh*N+"位数");
long[] r = new long[maxDim];
long group =(long) Math.pow(, d);//10的d次方,分组整除数
System.out.println("分组整除数="+group);
int top = ;//最高的数组下标位,计算的结果占的最高的数组下标
r[]=;
for(int i=;i<N;i++){
//先分别计算数组中每个数乘上基数后的值
for(int j=;j<=top;j++)
{
r[j] *= a;
}
//然后循环将低位的数产生的进位累加到高位,如果最高位后还有进位,
//再对最高位的数进行d位分组
long temp = r[];//初始最低位开始
for(int j=;j<=top;j++){
r[j]=temp%group;//保留d位
//将进位累加到高位,此处易发生数组边界越界,所以维数+2
temp=r[j+]+temp/group;
//如果是最高位后的进位大于0,则再进行d位分组
if(j==top&&temp>)
{
top++;
r[top] = temp%group;
while(temp/group>){
temp /= group;
top++;
r[top]=temp%group;
}
break;
}
}
//System.out.println("N="+i+"时:"+output(r,top));
}
//输出结果
long dt = new Date().getTime()-startTime;
System.out.println("实际数组维数:"+(top+)+",实际的结果位数:"+(top*d+Long.toString(r[top]).length()));
System.out.println("共执行毫秒数:"+dt);
return output(r,top,d);
}
private static String output(long[] r,int top,int d)
{
StringBuilder result = new StringBuilder();
for(int i=top;i>=;i--)
{
if(i!=top) result.append(" ");
//注意输出时不够d位的要补0
String format = "%"+d+"d";
if(i==top)
result.append(String.format(format, r[i]));
else
result.append(String.format(format, r[i]).replace(" ", "0"));
if(i%==) result.append("\r\n");
}
return result.toString();
}
}
计算2的1024次幂:
数组每个数的位数=16,数组维数=66,最高共1024位数
分组整除数=10000000000000000
实际数组维数:19,实际的结果位数:309
共执行毫秒数:1
17976 9313486231590772 9305190789024733 6179769789423065 7273430081157732
6758055009631327 0847732240753602 1120113879871393 3576587897688144 1662249284743063
9474124377767893 4248654852763022 1960124609411945 3082952085005768 8381506823424628
8147391311054082 7237163350510684 5862982399472459 3847971630483535 6329624224137216
计算99的99次幂:
数组每个数的位数=15,数组维数=15,最高共198位数
分组整除数=1000000000000000
实际数组维数:13,实际的结果位数:198
共执行毫秒数:0
369 729637649726772 657187905628805 440595668764281
741102430259972 423552570455277 523421410650010 128232727940978 889548326540119
429996769494359 451621570193644 014418071060667 659301384999779 999159200499899