问题描述
求两个大的正整数相除的商
输入数据
第 1 行是测试数据的组数n,每组测试数据占2 行,第1 行是被除数,第2 行是除数。
每组测试数据之间有一个空行,每行数据不超过100 个字符
输出要求
n 行,每组测试数据有一行输出是相应的整数商
输入样例
3
2405337312963373359009260457742057439230496493930355595797660791082739646
2987192585318701752584429931160870372907079248971095012509790550883793197894
10000000000000000000000000000000000000000
10000000000
5409656775097850895687056798068970934546546575676768678435435345
1
输出样例
0
1000000000000000000000000000000
5409656775097850895687056798068970934546546575676768678435435345
解题思路
基本的思想是反复做减法,看看从被除数里最多能减去多少个除数,商就是多少。一个
一个减显然太慢,如何减得更快一些呢?以7546 除以23 为例来看一下:开始商为0。先减
去23 的100 倍,就是2300,发现够减3 次,余下646。于是商的值就增加300。然后用646
减去230,发现够减2 次,余下186,于是商的值增加20。最后用186减去23,够减8 次,
因此最终商就是328。
所以本题的核心是要写一个大整数的减法函数,然后反复调用该函数进行减法操作。
计算除数的10 倍、100 倍的时候,不用做乘法,直接在除数后面补0 即可。
#include "IntegerDivision.h"
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
string divide();
int subtract();
string num1, num2;
void main()
{
cout << "Please input numbers!" << endl;
cout << "num1:";
cin >> num1;
cout << "num2:";
cin >> num2;
string r;
r = divide();
cout << r << endl;
}
string divide()
{
int len1, len2;
len1 = num1.size();
len2 = num2.size();
if (len1 == len2)
{
if (num1 > num2)
return "1";
return "0";
}//除数于被除数长度相同
else if (len1 < len2)
{
return "0";
}//除数长度小于被除数,直接返回0
else
{
int p = len1 - len2;
for (int i = 0; i < p; i++)
{
num2 += "0";
}
char res[] = "00000000000000000000000000000000000000000000000000000000000000";//保存除的结果
while (p >= 0)
{
int t = 0;
while (subtract() >= 0)
{
t++;
}
res[(sizeof(res) / sizeof(char)) - p - 1] = t + '0';
p--;
num2 = num2.substr(0, len2 + p);
}
int t;
for (int m = 0; m < (sizeof(res) / sizeof(char)); m++)
{
if (res[m] != '0')
{
t = m;
break;
}
}
return res + t;
}//除数长度大于被除数长度
}
int subtract()
{
int len1, len2;
len1 = num1.size();
len2 = num2.size();
int arr[100];
if (len1 >= len2)
{
if (len1 == len2 && num1 < num2)
return -1;
for (int i = 0; i < len1; i++)
{
if (i < len2)
arr[i] = num1[len1 - i - 1] - num2[len2 - 1 - i];
else
{
arr[i] = num1[len1 - 1 - i] - '0';
}
}
for (int j = 0; j < len1; j++)
{
if (arr[j] < 0)
{
arr[j] += 10;
arr[j + 1] -= 1;
}
}
int k;
for (int b = len1 - 1; b >= 0; b--)
{
if (arr[b] != 0)
{
k = b;
break;
}
}
string s = "";
for (int x = k; x >= 0; x--)
{
char t[3];
s += _itoa_s(arr[x], t, 10);
}
num1 = s;
return 1;
}
else
{
return -1;
}
}
#include<iostream>
#include<string>
using namespace std;
bool Compare(string first, string second)
{
int i = 0;
while ('0' == first[i])
i++;
first.erase(0, i);
i = 0;
while ('0' == second[i])
i++;
second.erase(0, i);
int len1 = first.size();
int len2 = second.size();
if (len1 < len2)
return false;
else if (len1 == len2 && first < second)
return false;
return true;
}
string Subtraction(string s1, string s2)
{
if (s1 == s2)
return "0";
int len1 = s1.size();
int len2 = s2.size();
for (int i = len2 - 1; i >= 0; i--)
{
s1[len1 - 1 - i] = '0' + s1[len1 - 1 - i] - s2[len2 - 1 - i]; //不要忘了加‘0’
}
//cout<<s1<<endl;
for (int i = len1 - 1; i >= 0; i--)
{
if (s1[i] < '0')
{
s1[i] += 10;
s1[i - 1]--;
}
}
int i = 0;
while (s1[i] == '0')
i++;
s1.erase(0, i); //去掉字符串前面的0
//cout<<s1<<endl;
return s1;
}
void BigDivision(string a, string b)
{
string result, s; //result用来保存商,s用来保存每次的运算时的被除数及最后的余数
int count, i;
if ("0" == b)
{
//cout<<"Error,divisor can not be zero!"<<endl;
cout << "NULL" << endl;
return;
}
if (!Compare(a, b))
{
//cout<<"商:"<<0<<",余数:"<<a<<endl;
cout << 0 << " " << a << endl;
return;
}
int len = a.size();
for (int i = 0; i < len; i++)
{
count = 0;
s.push_back(a[i]);
while (Compare(s, b))
{
s = Subtraction(s, b);
count++;
}
result += char(count + '0'); //s>b时加每次相除得到的商或者,s<b时补0
}
//cout<<s<<endl;
i = 0;
while ('0' == result[i])
i++;
result.erase(0, i);
i = 0;
while ('0' == s[i])
i++;
s.erase(0, i);
//cout<<"商为:"<<result<<",余数: "<<s<<endl;
cout << result << " " << s << endl;
}
int main()
{
string str1, str2;
while (cin >> str1 >> str2)
//cout<<subtraction(str1,str2)<<endl;
BigDivision(str1, str2);
}