import java.math.BigInteger;
import java.util.Scanner;
import org.junit.Test;
public class Inter {
@Test
public void bigMultiply()
{
Scanner sc=new Scanner(System.in);
//输入两个字符串
String s1=sc.next();
String s2=sc.next();
//记录下数字串的长度,以后要使用
int n1=(s1.trim()).length();
int n2=(s2.trim()).length();
//创建两个数组,来存放数组的每一位
int a1[]=new int[n1];
int a2[]=new int[n2];
//赋值,这里需要注意的是要倒序来赋值
for(int i=0;i<n1;i++)
a1[i]=Integer.parseInt(s1.charAt(n1-1-i)+"");
for(int i=0;i<n2;i++)
a2[i]=Integer.parseInt(s2.charAt(n2-1-i)+"");
//一个二维数组,来模拟每次相乘的时候的结果
int results[][]=new int[n2][n1+n2];
for(int i=0;i<n2;i++)
{
for(int j=0;j<n1;j++)
{
results[i][i+j+1]+=(a1[j]*a2[i])/10;//向上一位进位
results[i][i+j]+=(a1[j]*a2[i])%10;//本位数字要加上原来的进位,所以是+=
}
}
//一维数组记录最后的结果
int result[]=new int[n1+n2+1];
//进位标志
int jin=0;
for(int i=0;i<n1+n2;i++)
{
int sum=0;
sum+=jin;
for(int j=0;j<n2;j++)
{
sum+=results[j][i];
}
jin=sum/10;
result[i]=sum%10;
}
int index=n1+n2-1;
//将前几位为零的省略
while(result[index]==0)
index--;
//输出最后的结果
for(int i=index;i>=0;i--)
System.out.print(result[i]);
}
@Test
public void moni()
{
Scanner sc=new Scanner(System.in);
String s1=sc.next();
String s2=sc.next();
BigInteger b1=new BigInteger(s1.trim());
BigInteger b2=new BigInteger(s2.trim());
BigInteger b=b1.multiply(b2);
System.out.println(b.toString());
}
}
大数相乘需要解决的是存储的问题。开始看到这个问题的时候,翻了翻算法课本,发现是用分治法,自己写了写,模拟了一下,发现到加法的时候还是无法避免溢出的问题,看到网上一些人们用的就是普通数组来做,我也采用了如此的方案,不过实现的步骤,我没有参考别人的,是完全按照自己算乘法的步骤来实现的。如果从思考上来说,不难,可是数组量大,而且还要考虑进位的问题,所以处理的时候有许多细节需要注意,比如说,你输入的数字,存入数组中的时候要先进行倒序,开始的时候我没有注意,算11*11是正确的,算25*25的时候就开始出错了,找了好半天才发现原来是存储的时候出了很大的问题。比如说,相乘进位的情况,如果不考虑当前运算对高位的影响,也就是不考虑向上进位,必然会出错了,而且计算的时候还要接收从低位进上来的。最后所有的中间结果进行相加的时候,更要注意进位的情况。
我用的是单元测试来做的,原来的题目要计算的是1234567891011121314151617181920*2019181716151413121110987654321,我先使用的是自己设计的算法,下面使用的是Java中的大整数来计算,结果是相同的,2492816912877266687794240983772975935013386905490061131076320
这个问题,现在想想还是很有意思的,有两天时间,闲来无事的时候我就开始拿笔模拟,感觉没有什么错误了就上机实践,可是总会出现一些意想不到的问题。不过,凭借着对问题的把握,还是可以找到问题的根源的。下次再碰到这样的问题就知道该怎么办了,所以,记录一下。