基本思想:
反复做减法,看看从被除数里最多能减去多少个除 数,商就是多少。
一个一个减显然太慢,如何减得更快一些呢?以 7546除以23为例来看一下:开始商为0。先减去23的100倍,就是2300,发现够减3次,余下646。于是商的值就增加300。然后用646减去230,发现够减2 次,余下186,于是商的值增加20。最后用186减去23,够减8次,因此最终商就是328。
所以本题的核心是要写一个大整数的减法函数,然后反复调用该函数进行减法操作。
算法逻辑:
int main()
{
读入输入数据组数;
while(输入未结束)
{
读入一组输入到szLine1/2 ,初始化减数an1、被减数数组an2;将szLine1/2中存储的字符串形式的整数转换 到 an1/2中去;
初始化结果数组anResult;
(1) 计算商的最高位位数, 用nShiftLen保存;
(2)while (余数>减数)
{
(3) 算出an1的10的nShiftLen次方倍;
(4) 重复减去an1的10的nShiftLen次方倍,看能减几次;
(5) 记录结果最高位的位置;
商的最高位位数nShiftLen减一;
}
输出结果;
}
}
问题:
(1)计算商的最高位位数, 用nShiftLen保存
nShiftLen = Length(MAX_LEN,an1) - Length(MAX_LEN,an2);定义函数Length求大整数的位数(从高位起找到第一个不为0 的位)。0 算0 位
int Length( int nMaxLen,int * an)
(2)余数>减数
Max(MAX_LEN,an1,an2) == an1
定义函数Max求大整数an1和an2里面大的那个,如果都是0, 则返回NULL(从高位起,若相等则依次比较,若不相等则返回)
int * Max(int nMaxLen, int * an1, int * an2)
(3)算出an1的10的nShiftLen次方倍
ShiftLeft(MAX_LEN, an2, tmpAn2,nShiftLen);
定义函数ShiftLeft将大整数an1左移n位,即乘以10的n次方,结果放到an2里(从高位起依次将i-n放入结果的i位,注意判断i - n 是否>=0)
void ShiftLeft( int nMaxLen, int * an1, int * an2, int n)
(4)重复减去an1的10的nShiftLen次方倍,看能减几次
while( Max(MAX_LEN,an1,tmpAn2) == an1)
{
Substract(MAX_LEN, an1,tmpAn2);
anResult[nShiftLen] ++;
}
定义减法函数Substract,参照前面大整数减法
(5)记录结果最高位的位置
if( nHighestPos == 0 && anResult[nShiftLen])
nHighestPos = nShiftLen;
#include <iostream>
#include <cstring>
#define MAX 100
using namespace std;
//求两个整数中的较大值
int Max(int x, int y)
{
return (x > y) ? x : y;
}
//两个大整数相减
int Substract(int nMaxLen, int *a1, int *a2)
{
int nStartPos = 0;
for(int i = 0; i < nMaxLen; ++i)
{
a1[i] -= a2[i];
if(a1[i] < 0)
{
a1[i + 1] --;
a1[i] += 10;
}
if(a1[i])
{
nStartPos = i;
}
}
return nStartPos;
}
//求大整数的长度,若为0位则返回0
int nLen(int nMaxLen, int *a)
{
for(int i = nMaxLen - 1; 0 <= i; --i)
if(a[i])
return i + 1;
return 0;
}
//求两个大整数中较大的那一个,如果都是0则返回NULL
int *MaxNum(int nMaxLen, int *a1, int *a2)
{
bool bBothZero = true;
for(int i = nMaxLen; 0 <= i; --i)
{
if(a1[i] > a2[i])
return a1;
else if(a2[i] > a1[i])
return a2;
else if(a1[i])
bBothZero = false;
}
if(bBothZero)
return NULL;
return a1;
}
//将大整数a左移n位,即乘以10的n次方,结果放在b中
void ShiftLeft(int nMaxLen, int *a, int *b, int n)
{
//将a复制到b
memcpy(b, a, nMaxLen * sizeof(int));
if(n <= 0)
return;
for(int i = nMaxLen - 1; 0 <= i; --i)
{
if(i >= n)
b[i] = a[i - n];
else
b[i] = 0;
}
}
int main()
{
int n;
cin >> n;
while(n--)
{
char *s1 = new char[MAX + 10]();
char *s2 = new char[MAX + 10]();
int *a1 = new int[MAX + 10]();
int *a2 = new int[MAX + 10]();
int *result = new int[MAX + 10]();
int *tmp = new int [MAX + 10]();
cin >> s1;
cin >> s2;
//将字符串转换为整型数组
int nLen1 = strlen(s1);
for(int i = nLen1 - 1, j = 0;0 <= i; --i)
{
a1[j++] = s1[i] - '0';
}
int nLen2 = strlen(s2);
for(int i = nLen2 - 1, j = 0; 0 <= i; --i)
{
a2[j++] = s2[i] - '0';
}
int nMaxLen = Max(nLen1, nLen2);
//输出
int nHighestPos = 0;
//计算商的最高位数
int nShiftLeft = nLen(nMaxLen, a1) - nLen(nMaxLen, a2);
while(MaxNum(nMaxLen, a1, a2) == a1)//余数 > 除数,继续循环
{
ShiftLeft(nMaxLen, a2, tmp, nShiftLeft);//计算a2的10的nShiftLeft倍
while(MaxNum(nMaxLen, a1, tmp) == a1)//循环减去a2的10的nShiftLeft倍
{
Substract(nMaxLen, a1, tmp);
result[nShiftLeft]++;//记录能减去的次数,即为商的位
}
if(nHighestPos == 0 && result[nShiftLeft])//记录商的最高位
nHighestPos = nShiftLeft;
nShiftLeft--;
}
for(int i = nHighestPos; 0 <= i; --i)
{
cout << result[i];
}
cout << endl;
delete [] s1;
delete [] s2;
delete [] a1;
delete [] a2;
delete [] result;
}
return 0;
}