Powerful Calculator(强大的计算器)(大整数运算)
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M 热度指数:3416
题目描述:
Today, facing the rapid development of business, SJTU recognizes that more powerful calculator should be studied, developed and appeared in future market shortly. SJTU now invites you attending such amazing research and development work. In most business applications, the top three useful calculation operators are Addition (+), Subtraction (-) and Multiplication (×) between two given integers. Normally, you may think it is just a piece of cake. However, since some integers for calculation in business application may be very big, such as the GDP of the whole world, the calculator becomes harder to develop. For example, if we have two integers 20 000 000 000 000 000 and 4 000 000 000 000 000, the exact results of addition, subtraction and multiplication are: 20000000000000000 + 4000000000000000 = 24 000 000 000 000 000 20000000000000000 - 4000000000000000 = 16 000 000 000 000 000 20000000000000000 × 4000000000000000 = 80 000 000 000 000 000 000 000 000 000 000 Note: SJTU prefers the exact format of the results rather than the float format or scientific remark format. For instance, we need “24000000000000000” rather than 2.4×10^16. As a programmer in SJTU, your current task is to develop a program to obtain the exact results of the addition (a + b), subtraction (a - b) and multiplication (a × b) between two given integers a and b.
输入描述:
Each case consists of two separate lines where the first line gives the integer a and the second gives b (|a| <10^400 and |b| < 10^400).
输出描述:
For each case, output three separate lines showing the exact results of addition (a + b), subtraction (a - b) and multiplication (a × b) of that case, one result per lines.
示例1
输入
20000000000000000
4000000000000000
输出
24000000000000000
16000000000000000
80000000000000000000000000000000
思路:
考察大整数运算中的加减乘法,涉及符号,更繁琐一些。
我的思路用一个含202个int的数组来表示一个数,每个数只存储4位。
(1)只存4位的原因是:如果5位,乘法运算时能到到10位,超过了int的表示范围。
(2)用202个而不是101个的原因是:乘法运算最大可能位数加倍。
最高位表示符号位,其他如果没有数就全置零。
加减法运算选择要看两个数的符号是否相同,并不给予原来算式中的加减法。
代码(C语言):
#include<stdio.h>
#include<string>
#include <stdlib.h>
#define N 202
#define M 10000
// 强力计算
int prase(char s[], int a[])
{
memset(a, 0, N*sizeof(int));
int n = strlen(s);
int flag = 0;
if (s[0] == '-' || s[0] == '+')
{
if (s[0] == '-')
flag = 1;
s++;
n--;
}
int i, j;
char t[5];
j = 0;
for (i=n-1; i>=0; i-=4)
{
int jj = 0;
for (int k=i-3; k<=i; k++)
{
if (k>=0)
t[jj++] = s[k];
}
t[jj] = '\0';
a[j++] = atoi(t);
}
a[N-1] = flag;
return j;
}
void printFirst(int a[], int n)
{
int i;
for (i=n-1; i>=0; i--)
{
if (a[i] != 0)
break;
}
if (i < 0)
{
printf("0\n");
return ;
}
int flag = a[N-1];
if (flag == 1)
printf("-");
printf("%d", a[i]);
for (int j=i-1; j>=0; j--)
printf("%04d", a[j]);
printf("\n");
}
int sub(int a[], int na, int b[], int nb, int c[])
{
int i;
for (i=0; i<na; i++)
{
if (a[i] < b[i])
{
a[i+1] --;
a[i] += M;
}
c[i] += a[i]-b[i];
}
for (i=na-1; i>=0; i--)
{
if (c[i] != 0)
break;
}
return i+1;
}
int add(int a[], int na, int flag, int b[], int nb, int c[])
{
memset(c, 0, N*sizeof(int));
int nm = (na > nb) ? na : nb;
int fa = a[N-1];
int fb = (b[N-1]+flag)%2;
int i;
if (fa == fb)
{
for (i=0; i<=nm; i++)
{
c[i] += a[i] + b[i];
if (c[i] >= M)
{
c[i+1] ++;
c[i] -= M;
}
}
c[N-1] = fa;
if (c[nm] != 0)
return nm + 1;
else
return nm;
}
int ns;
for (i=nm; i>=0; i--)
{
if (a[i] != b[i])
break;
}
if (i < 0)
return 0;
if (a[i] > b[i])
{
ns = sub(a, na, b, nb, c);
c[N-1] = fa;
}
else
{
ns = sub(b, nb, a, na, c);
c[N-1] = fb;
}
return ns;
}
int multiply(int a[], int na, int b[], int nb, int c[])
{
memset(c, 0, N*sizeof(int));
int i, j, k;
for (i=0; i<na; i++)
{
for (j=0; j<nb; j++)
{
k = i+j;
c[k] += a[i]*b[j];
if (c[k] >= M)
{
c[k+1] += c[k]/M;
c[k] %= M;
}
}
}
c[N-1] = (a[N-1]+b[N-1])%2;
for (i=na+nb; i>=0; i--)
{
if (c[i] != 0)
break;
}
return i+1;
}
int main(void)
{
char sa[2*N], sb[2*N];
int na, nb;
int a[N], b[N];
int np, ns, nm;
int p[N], s[N], m[N];
while (scanf("%s%s", sa, sb) != EOF)
{
na = prase(sa, a);
nb = prase(sb, b);
//printA(a, na);
//printA(b, nb);
np = add(a, na, 0, b, nb, p);
printFirst(p, np);
ns = add(a, na, 1, b, nb, s);
printFirst(s, ns);
nm = multiply(a, na, b, nb, m);
printFirst(m, nm);
}
return 0;
}
代码(C++):
#include<iostream>
#include<string>
using namespace std;
int a[500];
int b[500];
int sum[1000];
int sub[1000];
int mul[1000];
bool g(int a1[500],int b1[500]){
for(int i=499;i>=0;i--){
if(a1[i]>b1[i])
return true;
if(a1[i]<b1[i])
return false;
}
return true;
}
void add(){
int c=0;
for(int i=0;i<500;i++){
sum[i]=(a[i]+b[i]+c)%10;
c=(a[i]+b[i]+c)/10;
}
}
void dec(){
int c=0;
if(g(a,b)){
for(int i=0;i<500;i++){
if(a[i]-c>=b[i]){
sub[i]=a[i]-c-b[i];
c=0;
}else{
sub[i]=a[i]-c+10-b[i];
c=1;
}
}
}else{
for(int i=0;i<500;i++){
if(b[i]-c>=a[i]){
sub[i]=b[i]-c-a[i];
c=0;
}else{
sub[i]=b[i]-c+10-a[i];
c=1;
}
}
}
}
void multi(){
int c=0;
for(int i=0;i<500;i++)
for(int j=0;j<500;j++){
int tmp = mul[i+j];
mul[i+j]=(a[i]*b[j]+c+mul[i+j])%10;
c=(a[i]*b[j]+c+tmp)/10;
}
}
void showsum(string m1,string m2){
int ind=499;
if(m1=="+"&&m2=="+"||m1=="-"&&m2=="-"){
for(;ind>=0;ind--){
if(sum[ind]!=0)
break;
}
if(ind<0){
cout<<0<<endl;
}else{
if(m1=="-"&&m2=="-")
cout<<"-";
for(int i=ind;i>=0;i--){
cout<<sum[i];
}
cout<<endl;
}
}else{
for(;ind>=0;ind--){
if(sub[ind]!=0)
break;
}
if(ind<0){
cout<<0<<endl;
}else{
if(m1=="+"&&m2=="-"&&!g(a,b)||m1=="-"&&m2=="+"&&g(a,b)){
cout<<"-";
}
for(int i=ind;i>=0;i--){
cout<<sub[i];
}
cout<<endl;
}
}
}
void showdec(string m1,string m2){
int ind=499;
if(m1=="+"&&m2=="+"||m1=="-"&&m2=="-"){
for(;ind>=0;ind--){
if(sub[ind]!=0)
break;
}
if(ind<0){
cout<<0<<endl;
}else{
if(m1=="+"&&m2=="+"&&!g(a,b)||m1=="-"&&m2=="-"&&g(a,b)){
cout<<"-";
}
for(int i=ind;i>=0;i--){
cout<<sub[i];
}
cout<<endl;
}
}else{
for(;ind>=0;ind--){
if(sum[ind]!=0)
break;
}
if(ind<0){
cout<<0<<endl;
}else{
if(m1=="-"&&m2=="+")
cout<<"-";
for(int i=ind;i>=0;i--){
cout<<sum[i];
}
cout<<endl;
}
}
}
void showmul(string m1,string m2){
int ind=999;
for(;ind>=0;ind--){
if(mul[ind]!=0)
break;
}
if(ind<0){
cout<<0<<endl;
}else{
if(m1=="+"&&m2=="-"||m1=="-"&&m2=="+"){
cout<<"-";
}
for(int i=ind;i>=0;i--){
cout<<mul[i];
}
cout<<endl;
}
}
int main(){
string aa;
string bb;
while(cin>>aa>>bb){
string m1,m2;
int j=0;
for(int i=aa.length()-1;i>0;i--){
a[j++]=aa.at(i)-'0';
}
if(aa.at(0)=='-'){
m1="-";
}
else{
m1="+";
a[j]=aa.at(0)-'0';
}
j=0;
for(int i=bb.length()-1;i>0;i--){
b[j++]=bb.at(i)-'0';
}
if(bb.at(0)=='-'){
m2="-";
}else{
m2="+";
b[j]=bb.at(0)-'0';
}
add();
dec();
multi();
showsum(m1,m2);
showdec(m1,m2);
showmul(m1,m2);
for(int i=0;i<500;i++){
a[i]=0;
b[i]=0;
}
for(int i=0;i<1000;i++){
sum[i]=0;
sub[i]=0;
mul[i]=0;
}
}
return 0;
}