主要内容 #
- 商和余数的求法
- 高精度 / 高精度
1. 商和余数的求法 #
要分两种情况讨论:
- 高精度 / 低精度
- 高精度 / 高精度
2. 高精度 / 高精度 #
也就是说:假设 a 是一个高精度整数,b 也是一个高精度整数。
【算法分析】
- 方法:使用减法模拟除法
将被除数,不断减去除数,直到余数小于除数。
- 1. 需要用到高精度减法
- 2. 需要用到高精度比较大小
- 3. 需要用到高精度加法
【例程】
#include < iostream >
#include < string >
using namespace std;
int zero[] = { 0 };
int one[] = { 1 };
//赋值过程,将数组a[]中的数据赋值给b[],并将a的长度a_len赋值给b_len
void assign(int a[], int a_len, int* b, int& b_len)
{
for (int i=0; i < a_len; ++i)
b[i] = a[i];
b_len = a_len;
}
//高精度加法计算函数
void add(int a[], int a_len, int b[], int b_len, int* result, int& result_len)
{
int i = 0, x = 0;
result_len = 0;
int max_a_b = a_len > b_len ? a_len : b_len;
while (i< max_a_b)
{
int sub_a = i < a_len ? a[i] : 0;
int sub_b = i < b_len ? b[i] : 0;
result[i] = sub_a + sub_b + x;
x = result[i] / 10;
result[i] %= 10;
result_len++;
i++;
}
if (x != 0)
{
result[i] = x;
++result_len;
}
}
//高精度减法计算函数
void jianfa(int a[], int a_len, int b[], int b_len, int* result, int& result_len)
{
int i = 0, x = 0;
result_len = 0;
int max_a_b = a_len > b_len ? a_len : b_len;
while (i < max_a_b)
{
int sub_a = i < a_len ? a[i] : 0;
int sub_b = i < b_len ? b[i] : 0;
// 减法
if (sub_a < sub_b)
{
--a[i + 1];
sub_a += 10;
}
result[i] = sub_a - sub_b;
result_len++;
i++;
}
if (x != 0)
{
result[i] = x;
++result_len;
}
// 假如结果全都是0,输出一个0
int sum(0);
for (int i = 0; i < result_len; ++i)
{
sum += result[i];
if (sum != 0)
break;
}
if (sum == 0)
result_len = 1;
}
// 如果 a==b 返回 0; 如果 a > b, 返回 1; 如果 a < b, 返回 -1;
int compare_a_b(int a[], int a_len, int b[], int b_len)
{
if (a_len > b_len)
return 1;
else if (a_len < b_len)
return -1;
else
{
for (int i= a_len-1; i>=0; --i) // 加减的结果,是倒过来的,所以这里的比较也要倒着比较
{
if (a[i] > b[i])
return 1;
else if (a[i] < b[i])
return -1;
else
continue;
}
}
return 0; // 相等
}
void divide(int a[], int a_len, int b[], int b_len, int* shang, int& shang_len, int* yushu, int& yushu_len)
{
if (0 == compare_a_b(zero, 1, a, a_len))
{
shang_len = 1;
yushu_len = 1;
return; // 0是被除数,则商为0
}
for (;;)
{
jianfa(a, a_len, b, b_len, a, a_len); // 相当于 a -= b;
add(shang, shang_len, one, 1, shang, shang_len);
assign(a, a_len, yushu, yushu_len);// 将最终减法剩余的结果,赋值给余数
if (-1 == compare_a_b(a, a_len, b, b_len)) //
break; // 当余数a小于除数b的时候,退出循环。
}
}
int main()
{
// 从屏幕获得输入
string astr, bstr;
cin >> astr;
cin >> bstr;
int lena = astr.size(), lenb = bstr.size();
int a[100] = { 0 }, b[100] = { 0 };
for (int i = 0; i< lena; ++i)
a[lena - i - 1] = astr[i] - '0'; // 将数字倒过来
for (int i = 0; i< lenb; ++i)
b[lenb - i - 1] = bstr[i] - '0';
if (0 == compare_a_b(zero, 1, b, lenb))
return -1; // 被除数不能是 0
// 计算除法
int shang[100] = { 0 }, yushu[100] = { 0 }, shang_len(0), yushu_len(0);
divide(a, lena, b, lenb, shang, shang_len, yushu, yushu_len); // a 是被除数,是高精度值。b是低精度值,用 int 即可存储
// 输出
cout << "商:";
for (int i=0; i < shang_len; ++i)
cout << shang[shang_len - i - 1]; // 再将数字倒过来输出
cout << endl;
cout << "余数:";
for (int i = 0; i < yushu_len; ++i)
cout << yushu[yushu_len - i - 1]; // 再将数字倒过来输出
cout << endl;
return 0;
}
习题 #
请将上面的例题,独立完成一遍。要求必须掌握。下节课要求每个人都能够独立写出上面的代码。
课后练习