大数存储:由于x的位数最大为400位,我们不能用现有的int,longlong,double等数据类型进行存储。一般存储大数的方法是用一个字符串来表示。
方法:模拟小学生算术。
在这里我们先讨论全为正整数的情况哈。
大数加法
123
+ 23
146
对应位数相加,最后再进位,满十进一,为了方便计算,我们采用低位在前,高位在后的逆序存储相加后的结果。(两个数相加结果最大只会比较大的多一位)
123456+5677
6 | 5 | 4 | 3 | 2 | 1 |
7 | 7 | 6 | 5 | ||
13 | 12 | 10 | 8 | 2 | 1 |
C语言实现
#include<stdio.h>
#include<string.h>
const int maxn=1000+7;
using namespace std;
void plus(int a[],int b[],int len)
{
//给每一位作加法,满十进一
for(int i=0;i<len;i++)
{
a[i]+=b[i];
if(a[i]>=10)
{
a[i]-=10;
a[i+1]+=1;
}
}
//去掉前缀0
int flag=0;
for(int i=len;i>=0;i--)
{
if(a[i]!=0)
{
flag=1;
for(i=i;i>=0;i--)
printf("%d",a[i]);
break;
}
}
if(flag==0)
printf("0");
printf("\n");
}
int main()
{
char str2[maxn],str1[maxn];
int a[maxn],b[maxn];
int n,len1,len2,len;
scanf("%d",&n);
getchar();
while(n--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
scanf("%s%s",str1,str2);
len1=strlen(str1);
len2=strlen(str2);
if(len1>len2)
len=len1;
else
len=len2;
for(int i=0;i<len1;i++) //将字符编码的数字转换为对应的数
{
a[i]=str1[len1-i-1]-'0';
}
for(int i=0;i<len2;i++)
{
b[i]=str2[len2-i-1]-'0';
}
plus(a,b,len);
}
return 0;
}
Java实现
import java.math.BigInteger;
import java.util.Scanner;
public class 大数加法 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n =sc.nextInt();
for(int i=1;i<=n;i++){
BigInteger a = sc.nextBigInteger();
BigInteger b = sc.nextBigInteger();
System.out.println(a+" + "+b+" = "+a.add(b));
}
}
}
大数减法
和大数加法原理类似,对应位数相减,最后小于0的加10,它的后一位-1;
654321-2042
1 | 2 | 3 | 4 | 5 | 6 |
2 | 4 | 0 | 2 | ||
-1 | -2 | 3 | 2 | 5 | 6 |
该规则遵守大数减小数,因此先比较两个字符串的长度,长度长的数字大,长度相等,比较高位,如果相等依次类推。
我们可以把大数-小数直接进行上述的规则计算,小数-大数,可以交换他们的位置,变成为大数减小数,并在最前面加上负号。
c语言实现
#include<stdio.h>
#include<string.h>
const int maxn=1000+7;
using namespace std;
void sub(int a[],int b[],int len)
{
for(int i=0;i<len;i++)
{
a[i]-=b[i];
if(a[i]<0)
{
a[i]+=10;
a[i+1]-=1;
}
}
int flag=0;//删除前缀0
for(int i=len;i>=0;i--)
{
if(a[i]!=0)
{
flag=1;
for(i=i;i>=0;i--)
printf("%d",a[i]);
break;
}
}
if(flag==0)//结果为0时
printf("0");
printf("\n");
}
int main()
{
char str1[maxn],str2[maxn];
int len1,len2,a[maxn],b[maxn];
while(~scanf("%s%s",str1,str2))
{
len1=strlen(str1);
len2=strlen(str2);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<len1;i++)
{
a[i]=str1[len1-i-1]-'0';
}
for(int i=0;i<len2;i++)
{
b[i]=str2[len2-i-1]-'0';
}
if(len1>len2) //若减数长度>被减数,按照规则直接减
sub(a,b,len1);
else if(len1<len2)//若减数长度<被减数,用被减数-减数
{
printf("-");
sub(b,a,len2);
}
else //若减数长度==被减数长度,判断两个数每位的大小
{
for(int i=len1-1;i>=0;i--)//判断每一位两个数的大小
{
if(a[i]==b[i])
continue;
if(a[i]>b[i])//即减数大
{
sub(a,b,len1);
break;
}
if(a[i]<b[i])//即被减数大
{
printf("-");
sub(b,a,len1);
break;
}
}
}
}
return 0;
}
Java实现
import java.math.BigInteger;
import java.util.Scanner;
public class 大数减法 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n =sc.nextInt();
for(int i=1;i<=n;i++){
BigInteger a = sc.nextBigInteger();
BigInteger b = sc.nextBigInteger();
System.out.println(a+" - "+b+" = "+a.subtract(b));
}
}
}
我写的这个只能算a>b的情况。
大数乘法
模拟竖式计算
num1d的第i位与num2的第j位相乘,把结果放在结果的第i+j位上,每趟都进行相乘,每趟算出累加后的和,然后对这些相加结果进行进位。(积的位数最多是最大因数位数的两倍)
232*1234
4 | 3 | 2 | 1 | |||
2 | 8 | 6 | 4 | 2 | ||
3 | 12+6 | 9+4 | 6+2 | 3 | ||
2 | 8+9+4 | 6+6+2 | 4+3 | 2 | ||
8 | 18 | 21 | 14 | 7 | 2 |
c语言实现
#include<stdio.h>
#include<string.h>
const int maxn=1000+7;
using namespace std;
void multiply(int a[],int b[],int result[],int len1,int len2,int len)
{
int j;
for(int i=0;i<len1;i++)
{
for(j=0;j<len2;j++)
{
result[i+j]+=a[i]*b[j];
result[i+j+1]+=result[i+j]/10;
result[i+j]=result[i+j]%10;
}
}
int flag=0;
for(int i=2*len;i>=0;i--)
{
if(result[i]!=0)
{
flag=1;
for(i=i;i>=0;i--)
printf("%d",result[i]);
break;
}
}
if(flag==0)
printf("0");
printf("\n");
}
int main()
{
char str2[maxn],str1[maxn];
int a[maxn],b[maxn],result[maxn*2];
int n,len1,len2,len;
while(~scanf("%s%s",str1,str2))
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(result,0,sizeof(result));
len1=strlen(str1);
len2=strlen(str2);
if(len1>len2)
len=len1;
else
len=len2;
for(int i=0;i<len1;i++) //将字符编码的数字转换为对应的数
{
a[i]=str1[len1-i-1]-'0';
}
for(int i=0;i<len2;i++)
{
b[i]=str2[len2-i-1]-'0';
}
multiply(a,b,result,len1,len2,len);
}
return 0;
}
java实现
import java.math.BigInteger;
import java.util.Scanner;
public class 大数乘法 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n =sc.nextInt();
for(int i=1;i<=n;i++){
BigInteger a = sc.nextBigInteger();
BigInteger b = sc.nextBigInteger();
System.out.println(a+" * "+b+" = "+a.multiply(b));
}
}
}