需求
有一个很大的数,double都存不下,可能是小数,使用java计算它的平方。
原理
n位数的平方,其结果的位数范围是 (2n-1)~2n
以12345的自乘为例
在平行四边形的乘法子式阵列中,每一列进行相加操作,观察得知,i+j的值相等的会处在同一列。
比如左数第五列,5+1=4+2=3+3=2+4=1+5
(注意此处用了特殊的数字12345,对应实际数字的序号,换成其它数字要用序号去理解。)
理解了这一点就好办了。
Java实现
把数以字符串的方式传入,拆分成char字符串,按位相乘,从数字低位开始相乘,所以从数组的高位开始计算。
char[i]*char[j] 的值存入 char[i+j+1] 中,然后处理进位的问题。
如果含有小数点,提前记录小数的位数,然后在字符串中把小数点去掉,按整数的方式计算完毕后,再把小数点加进去。
public class BigNumPow {
public static void pow2(String num) {
int decimals=-1;
//如果数字是小数
if(num.contains(".")){
//记录小数的位数
decimals=num.length()-num.indexOf(".")-1;
//去掉字符串中的小数点
num=num.replace(".","");
}
char[] ch = num.toCharArray();//将String类型转化为char类型的数组
int len = ch.length;//length属性获取ch数组字符个数
int[] in = new int[len];
//把字符转化为数字存储到数组中
for (int i = 0; i < len; i++) {
in[i] = Integer.parseInt(String.valueOf(ch[i]));
}
//result按位存放结果,n位数的平方最多有2*n位
int[] result = new int[len * 2];
//计算本位,下标i+j相等的相加存放在result[i+j+1]中
for (int i = len - 1; i >= 0; i--) {
for (int j = len - 1; j >= 0; j--) {
result[i + j + 1] += in[i] * in[j];
}
}
//计算进位
for (int i = result.length - 1; i >= 0; i--) {
if (result[i] > 9) {
//把有进位的(两位数)数的个位和十位分离,个位数result[i]%=10放入本位,十位数result[i]/10作为进位放入前一位
result[i - 1] += result[i] / 10;
result[i] %= 10;
}
}
//results以append方式按位添加,得到最终结果
StringBuilder results = new StringBuilder();
for (int value : result)
results.append(value);
//如果没有进位到首位(总位数是2*n-1),则首位是0,需要把0去掉
if (results.charAt(0)==48) {
results.deleteCharAt(0);
}
//如果是小数,把小数点添加上
if(decimals>0){
results.insert(results.length()-2*decimals,".");
}
System.out.println(results);
}
//测试
public static void main(String[] args) {
String num = "547647345435";
pow2(num);
}
}