前言
本期我们分享用C语言实现高精度除法,可通过该题测试点我点我,洛谷 p2005。
那么话不多说我们开始吧。
讲解
大家还记不记得小学的时候我们是怎么做除法的?我们以111÷5为例。
我们的高精度除法也将采用这个思路进行,分别用两个数组储存数字a和b的值,翻转后,从相对最高位开始相除,虽然我们不好实现除法,但是我们可以实现减法,比如11÷5可以理解为11-5-5这样商就是2余数就是1,也就是所我们可以弄一个减法的循环直到不能再减就退出循环。那么我们在相减之前就需要判断两者的大小,比如1和5明显没法再减了,我们就需要跳到下一位再重新进行减法循环。
大致的思路就是这样,下面我们用代码讲解:
#include <stdio.h>
#include<string.h>
char arra[20000] = { 0 }, arrb[20000] = { 0 };//分别储存a,b的值
int ans[20000] = { 0 };//储存商
int judge(char* arr1, char* arr2, int len)//判断是否可以相减的函数
{
if (arr1[len] >'0') return 1; //如果arr1比arr2长, 则可以除
for (int i = len - 1; i >= 0; i--) {//从arr的最高位开始与arr2比较
if (arr1[i] > arr2[i]) return 1;//相同位时arr1中的数字更大,则可以相除
else if (arr1[i] < arr2[i]) return 0;//相同位时arr1数字更小则不能相除
}
return 1;//arr1和arr2完全一样,可以相除
}
void my_reverse(char* arr, int len)//翻转函数
{
for (int i = 0; i < len - 1; i++, len--)
{
char temp = arr[i];
arr[i] = arr[len - 1];
arr[len - 1] = temp;
}
}
void print_div(int len1, int len2, char* arr1, char* arr2, int* ans)
{
for(int i = len1-len2;i>=0;i--)//从最高位开始
{
while (judge(arr1 + i, arr2, len2))//判定是否可以相减
{
for (int j = 0; j < len2; j++)//高精度减法
{
if (arr1[i + j] < arr2[j])
{
arr1[i + j + 1] -= 1;
arr1[i + j] += 10;
}
arr1[i + j] -= (arr2[j] - '0');
}
ans[i]++;//ans[i]不可能>10
}
}
int len_ans = len1 - len2;//ans的长度
while (arr1[len1] == '0' && len1 > 0) len1--;//去掉前缀无用的零
while (ans[len_ans] == 0 && len_ans > 0) len_ans--;
for (int i = len_ans; i >= 0; i--)//打印商
{
printf("%d", ans[i]);
}
printf("\n");
//如果想要得到余数,则直接打印arr1即可,此时arr1存储的正是余数需要余数直接把下面的注释消掉即可
//if (len1 > 0||arr1[0]>='0')
// for (int i = len1 - 1; i >= 0; i--)
// printf("%c", arr1[i]);
}
int main()
{
scanf("%s %s", arra, arrb);
int lena = strlen(arra);//计算a和b的长度
int lenb = strlen(arrb);
my_reverse(arra, lena);
my_reverse(arrb, lenb);
print_div(lena, lenb, arra, arrb, ans);
return 0;
}