1.问题描述
两个大数相除。输入是两个长的字符串,实现两个数的相除。得到结果的商和余数。
例如:
输入:
2345678910
345678910
输出结果是:
6 271605450
2.代码(分析在代码中)
#include<iostream>
#include <sstream>
using namespace std;
//比较两个字符串前者是否大于等于后者
bool Compare(string first,string second)
{
int len1=first.size();
int len2=second.size();
if(len1<len2)
return false;
else if(len1==len2 && first<second)
return false;
return true;
}
string sub(string num1,string num2)
{
//fushu用来判断最后结果是否是负数
bool fushu = false;
//如果被减数位数小于减数,那么结果是负数,同时两个字符串交换顺序,大的数减小的数
if(num1.size()<num2.size())
{
string temp = num1;
num1 = num2;
num2 = temp;
fushu = true;
}
//两个数长度一样,这个时候,需要判断哪个数更大,如果被减数小于减数,那么结果是负数,同时两个字符串交换顺序,大的数减小的数
else if(num1.size() == num2.size())
{
int len = num1.size();
for(int i=0;i<len;++i)
{
if(num1[i] == num2[i])
continue;
if(num1[i]>num2[i])
break;
if(num1[i]<num2[i])
{
string temp = num1;
num1 = num2;
num2 = temp;
fushu = true;
}
}
}
int lenNum1 = num1.size();
int lenNum2 = num2.size();
//用来保存结果
int* result = new int[lenNum1];
int index = 0;
//num1 31 num2 29 result 1,3
//把被除数的结果先放到result中
for(int i=lenNum1-1;i >=0;--i)
result[index++]=num1[i]-'0';
//进行减法操作
index = 0;
for(int i=lenNum2-1;i>=0;--i)
{
int num = num2[i]-'0';
//如果减数 大于 被减数,则需要退位
if(num>result[index])
{
result[index+1] -=1;
result[index] = 10+result[index] - num;
}
//直接相减
else
result[index] = result[index] - num;
++index;
}
//清除result尾部的0,index从右到左遍历,直到第一个不是0为止
index = lenNum1-1;
while(result[index] == 0)
--index;
//使用stringstream流,方便把数组输出到字符串中
ostringstream osstr;
//判断是否结果是负数
if(fushu == true)
osstr<<'-';
for(int i=index;i>=0;--i)
osstr<<result[i];
delete result;
return osstr.str();
}
void div(string a,string b)
{
//result为商,s为余数
string s;
ostringstream result;
int count,i;
if("0"==b)
{
//cout<<"Error,divisor can not be zero!"<<endl;
cout<<"NULL"<<endl;
return;
}
//这部分代码是去除字符串开始的字符0
{
int index=0;
while('0'==a[index])
index++;
//去掉字符串前缀0
a.erase(0,index);
index=0;
while('0'==b[index])
index++;
//去掉字符串前缀0
b.erase(0,index);
}
//如果被除数小于除数,那么商为0,余数为被除数
if(!Compare(a,b))
{
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=sub(s,b);
//统计被减次数
count++;
}
//因为是模拟除法,count不会大于9的
if(count != 0)
result<<count; //s>b时加每次相除得到的商或者,s<b时补0
}
//cout<<"商为:"<<result<<",余数: "<<s<<endl;
cout<<result.str()<<" "<<s<<endl;
}
int main()
{
string str1,str2;
while(cin>>str1>>str2)
//cout<<subtraction(str1,str2)<<endl;
div(str1,str2);
return 0;
}
3.测试
输入:
5044
123
输出:
41 1
输入:
2345678910
345678910
输出:
6 271605450
4.总结
其实大数相除,就是一个不断相减的过程,这个相减需要从高位减到低位。其中还有一个关键就是我们需要借助大数相减这个函数,我们才好模拟相减。还需要一个函数判断我们被减数是否>=减数,这样我们就可以很好的手工模拟除法过程了。