问题
大数乘法
对于32位字长的机器,大约超过20亿,用int类型就无法表示了,我们可以选择int64类型,但无论怎样扩展,固定的整数类型总是有表达的极限
如果对超级大整数进行精确运算呢?一个简单的办法是:仅仅使用现有类型,但是把大整数的运算化解为若干小整数的运算,即所谓:“分块法”
每一个数可以分成两个或以上的数相乘,最终对结果进行累加
x2 x1
X y2 y1
/ -----------
m1 m1 ->( y1 * x1)
m2 m2 ->( y1 * x2)
m3 m3 ->( y2 * x2 )
m4 m4 ->( y2 * x2)
/-------------
r0 r1 r2 r3
上图表示了分块乘法的原理。可以把大数分成多段(此处为2段)小数,然后用小数的多次运算组合表示一个大数
可以根据int的承载能力规定小块的大小,比如要把int分成2段,则小块可取10000为上限值。注意,小块在进行纵向累加后,需要进行进位校正
解题
/**
* 大数乘法
* 对于32位字长的机器,大约超过20亿,用int类型就无法表示了,我们可以选择int64类型,但无论怎样扩展,固定的整数类型总是有表达的极限
* 如果对超级大整数进行精确运算呢?一个简单的办法是:仅仅使用现有类型,但是把大整数的运算化解为若干小整数的运算,即所谓:“分块法”
* 每一个数可以分成两个或以上的数相乘,最终对结果进行累加
* x2 x1
* X y2 y1
* -----------
* m1 m1 ->( y1 * x1)
* m2 m2 ->( y1 * x2)
* m3 m3 ->( y2 * x2 )
* m4 m4 ->( y2 * x2)
*-------------
* r0 r1 r2 r3
*
* 上图表示了分块乘法的原理。可以把大数分成多段(此处为2段)小数,然后用小数的多次运算组合表示一个大数
* 可以根据int的承载能力规定小块的大小,比如要把int分成2段,则小块可取10000为上限值。注意,小块在进行纵向累加后,需要进行进位校正
*
*/
public static void BigNumberMul(int bigNumber1, int bigNumber2, int r[]){
// 标准1
int base = 10000;
// 对大数进行拆分 最终拆分结果还是等于两数之积
int x2 = bigNumber1 / base;
int x1 = bigNumber1 % base;
int y2 = bigNumber2 / base;
int y1 = bigNumber2 % base;
// 拆分后中间结果
int sum1 = y1 * x1;
int sum2 = y2 * x1;
int sum3 = y1 * x2;
int sum4 = y2 * x2;
r[3] = sum1 % base;
r[2] = sum1 / base + sum2 % base + sum3 % base;
r[1] = sum2 / base + sum3 / base + sum4 % base;
r[0] = sum4 / base;
r[1] += r[2] / base;
r[2] = r[2] % base;
r[0] += r[1] / base;
r[1] = r[1] % base;
StringBuilder stringBuilder = new StringBuilder();
if (r[0] == 0){
System.out.println(stringBuilder.append(r[1]).append(r[0]).append(r[2]).append(r[3]));
} else {
System.out.println(stringBuilder.append(r[0]).append(r[1]).append(r[2]).append(r[3]));
}
}