• C++
  • 高精除以高精,求它们的商和余数。

  • @ 2023-5-8 14:26:47

高精除以高精,求它们的商和余数。

【算法分析】

高精除以低精是对被除数的每一位(这里的“一位”包含前面的余数,以下都是如此)都除以除数。

高精除以高精则是用减法模拟除法,对被除数的每一位都减去除数,一直减当前位置的数字(包含前面的余数)小于除数(由于每一位的数字小于10,所以对于每一位最多进行10次计算),具体实现

< 方法一 >:

#include<iostream>
#include<cstring>
using namespace std;
int a[101], b[101], c[101], d, i;
void init(int a[]) { //获取字符串 并将字符串逆向存储转换为数组
	string s;
	cin >> s;
	a[0] = s.length(); //a[0]储存字符串的长度
	for (i = 1; i <= a[0]; i++)
		a[i] = s[a[0] - i] - '0';
}
void print(int a[]) { //打印函数 逆向输出
	if (a[0] == 0) {
		cout << 0 << endl;
		return ;
	}
	for (int i = a[0]; i > 0; i--) cout << a[i];
	cout << endl;
	return ;
}
int compare(int a[], int b[]) { //比较函数 a>b返回1;a<b返回-1;a=b返回0
	if (a[0] > b[0]) return 1;
	if (a[0] < b[0]) return -1;
	for (int i = a[0]; i > 0; i--) { //从高位向低位比较
		if (a[i] > b[i]) return 1;
		if (a[i] < b[i]) return -1;
	}
	return 0;//每一位都相等
}
void jian(int a[], int b[]) {
	int flag, i;
	flag = compare(a, b);
	if (flag == 0) {
		a[0] = 0;
		return;
	}
	if (flag == 1) {
		for (i = 1; i <= a[0]; i++) {
			if (a[i] < b[i]) { //处理借位
				a[i + 1]--;
				a[i] += 10;
			}
			a[i] -= b[i];
		}
		while (a[0] > 0 && a[a[0]] == 0) a[0]--; //修正位数
		return;
	}
}
void numcpy(int p[], int q[], int det) { //将p数组拷贝到q数组中,从q的det位置开始
	for (int i = 1; i <= p[0]; i++)q[i + det - 1] = p[i];
	q[0] = p[0] + det - 1; //更新q的位数
}
void chu(int a[], int b[], int c[]) { //除法运算函数
	int i, tmp[101];
	c[0] = a[0] - b[0] + 1; //确定商的位数
	for (i = c[0]; i > 0; i--) {
		memset(tmp, 0, sizeof(tmp));
		numcpy(b, tmp, i);
		while (compare(a, tmp) >= 0) { //减法模拟除法运算过程
			c[i]++;
			jian(a, tmp);
		}
	}
	while (c[0] > 0 && c[c[0]] == 0) c[0]--;
	return ;
}
int main() {
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(c, 0, sizeof(c));
	init(a);
	init(b);
	chu(a, b, c);
	print(c);
	print(a);
	return 0;
}

< 方法二 >:

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAX 400

void IntToChar(int Arr[], char str[], int begin, int end) {
	for (int i = begin; i < end; i++)	str[i] = Arr[i] + '0';
	str[end] = '\0';
}
void CharToInt(char str[], int Arr[]) {
	int i = 0;
	while (str[i] != '\0')	Arr[i] = str[i++] - '0';
}
void swap(int &a, int &b) {
	int t = a;
	a = b;
	b = t;
}
void filterZero(char a[]) {
	int l;
	while (a[0] == '0' && a[1] != '\0')	{
		l = strlen(a);
		for (int i = 0; i < l; i++)	a[i] = a[i + 1];
	}
}
void sub( char s1[], char s2[], char s3[]) {
	char a[MAX] = {0}, b[MAX] = {0};
	int ia[MAX] = {0}, ib[MAX] = {0}, ic[MAX] = {0};
	int size, la, lb;
	bool flag = false; //符号位
	filterZero(s1), filterZero(s2);
	la = strlen(s1), lb = strlen(s2);
	if (la < lb || (la == lb && strcmp(s1, s2) < 0)) {
		flag = true;  //结果为负数
		strcpy(a, s2), strcpy(b, s1); //复制被减数和减数
		swap(la, lb);
	} else 	strcpy(a, s1), strcpy(b, s2); //复制被减数和减数
	size = la > lb ? la : lb;
	reverse(a, a + la), reverse(b, b + lb);
	CharToInt(a, ia);
	CharToInt(b, ib);
//减法
	for (int i = 0; i < size; i++) {
		ic[i] += ia[i] - ib[i];
		if (ic[i] < 0) {
			ic[i + 1]--;
			ic[i] += 10;
		}
	}
//输出
	bool bOut = false;
	int k = 0;
	if (flag)  s3[k++] = '-';
	for (int i = size; i >= 0; i--) {
		if (ic[i]) bOut = true;
		if (bOut) s3[k++] = ic[i] + '0';
	}
//正好为0的情况
	if (k == 0) s3[k++] = '0';
	s3[k] = '\0';
}
int main(int argc, char *argv[]) {
	char a[MAX] = {0}, b[MAX] = {0};
	int c[MAX] = {0};
	char bcx[MAX], bk[MAX];
	int size, la, lb, k;
	cin >> a >> b;
	la = strlen(a), lb = strlen(b);
//特殊情况不够除直接输出结果
	if (la < lb || (la == lb && strcmp(a, b) < 0)) {
		cout << "0" << endl << a << endl;
		return 0;
	}
	size = la - lb + 1; //确定除的次数
//除法模拟
	for (int i = 0; i < size; i++) {
		if (i == 0) {
			strncpy(bcx, a, lb); //根据除数的长度确定开始的被除数
			bcx[lb] = '\0';
		} else {
			k = strlen(bcx);
			bcx[k] = a[lb + i - 1], bcx[k + 1] = '\0';
		}
//尝试减法
		k = 0;
		sub(bcx, b, bk); //bk为高精度减法结果数据
		while (bk[0] != '-') {
			k++;
			strcpy(bcx, bk); //将减的结果更新为被减数
			sub(bcx, b, bk); //继续尝试减法
		}
		c[i] = k; //保存结果
	}
//输出商
	bool bOut = false;
	for (int i = 0; i < size; i++) {
		if (c[i]) bOut = true;
		if (bOut) cout << c[i];
	}
//输出余数
	cout << endl << bcx << endl;

	return 0;
}

2 条评论

  • @ 2023-5-9 1:25:10
    例1
    分析:
    高精除以高精则是用减法模拟除法,先以前面介绍的方式以读字符串的方式读取两个数并转化倒序存储到整型数组a和b中,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数(由于每一位的数字小于10,所以对于每一位最多进行10次计算)。
    
    具体步骤:
    下面以12345678(存在数组a中)除以11111组b中)为例模拟整个运算过程(用c数组存商)。
    第一步:确定商的最大位数。c[0]=a[0]-b[0]+1;即c[0]=4;
    第二步:循环减数i从c[0]开始依次递减循环。
    
    步骤1、定义一个中间数组temp用来保存,将temp清零,从第i位开始将b的数值赋值给temp。
    当i=4的时候将b数组所有的数据右移3(i-1)格,并存储在temp数组中
    存储位 0   1   2   3   4   5   6   7   8
    a   8   8   7   6   5   4   3   2   1   。
    b   5   1   1   1   1   1
    temp  8   0   0   0   1   1   1   1   1
    该部分子函数代码如下:(p是数b所在数组,q是数组tmp)
    void numcpy(int p[],int q[],int det) //复制p到q从det开始的地方
    {
    for (int i=1;i<=p[0];i++) q[i+det-1]=p[i];//将数组右移,使两个数组右端对齐,形参q数组储存右移后的结果
    q[0]=p[0]+det-1;
    }
    
    步骤2、比较数组a和tmp的大小。比较方法,先判断两个数的位数,a的位数多则返回1,temp的位数多则返回-1;如果位数相同则从高位开始逐位判断大小,只要在某一位上出现大小不等的情况那么直接返回相应的比较结果(a[i]>b[i]返回1;a[i]b则为1,若ab[0]) return 1;  //若a的位数大于b,则a>b
    if (a[0]0;i--)//从高位到低位依次比较,找出大小关系
    {
    if (a[i]>b[i]) return 1;
    if (a[i]
    
    • @ 2023-5-9 1:24:08
      #include<iostream>
      #include<cstring>
      using namespace std;
      
      void init(int a[]) {
      	char s[101];
      	cin >> s; //读入字符串
      	a[0] = strlen(s);    //a[0]储存字符串的长度
      	for (int i = 1; i <= a[0]; i++)
      		a[i] = s[a[0] - i] - '0'; //将字符串转化为数组a,并倒序储存
      }
      int compare(int a[], int b[]) { //比较a和b的大小关系,若a>b则为1,若a<b则为-1,若a=b则为0
      	int i;
      	if (a[0] > b[0]) return 1; //若a的位数大于b,则a>b
      	if (a[0] < b[0]) return -1; //若a的位数小于b,则a<b
      	for (i = a[0]; i > 0; i--) { //从高位到低位依次比较,找出大小关系
      		if (a[i] > b[i]) return 1;
      		if (a[i] < b[i]) return -1;
      	}
      	return 0;
      }
      void printOut(int a[]) { // 用于输出最后的答案,并注意若答案为0的情况
      	int i;
      	if (a[0] == 0) {
      		cout << "0" << endl;
      		return;
      	}
      	for (i = a[0]; i > 0; i--) cout << a[i];
      	cout << endl;
      	return;
      }
      
      void sub(int a[], int b[]) { //a数组既做被除数,又作为储存余数
      	int pd, i;
      	pd = compare(a, b);         //调用函数比较ab大小
      	if (pd == 0) {
      		a[0] = 0;    //相等
      		return;
      	}
      	if (pd == 1) {
      		for (i = 1; i <= a[0]; i++) {
      			if (a[i] < b[i]) {
      				a[i + 1]--;    //若不够减上借一位
      				a[i] += 10;
      			}
      			if (a[i] >= b[i]) a[i] -= b[i];
      		}
      		while ((a[a[0]] == 0) && (a[0] > 0)) a[0]--;
      		return;
      	}
      }
      
      void numcpy(int p[], int q[], int det) { //复制p到q从wei开始的地方
      	for (int i = 1; i <= p[0]; i++) q[i + det - 1] = p[i]; //将数组右移,使两个数组右端对齐,形参q数组储存右移后的结果
      	q[0] = p[0] + det - 1;
      }
      void div(int a[], int b[], int c[]) {
      	int i, tmp[101];
      	c[0] = a[0] - b[0] + 1; //商的最大位数
      	for (i = c[0]; i > 0; i--) {
      		memset(tmp, 0, sizeof(tmp));   //temp数组清零
      		numcpy(b, tmp, i);             //将除数b右移后复制给tmp数组,注意用i控制除数位数
      		while (compare(a, tmp) >= 0) {
      			c[i]++;    //减法模拟除法,并计数
      			sub(a, tmp);
      		}
      	}
      	while ((c[c[0]] == 0) && (c[0] > 0)) c[0]--; // 控制最高位的0
      }
      
      int main() {
      	int a[101], b[101], c[101];
      	memset(a, 0, sizeof(a));
      	memset(b, 0, sizeof(b));
      	memset(c, 0, sizeof(c));
      	init(a);
      	init(b);
      
      	div(a, b, c);
      
      
      	printOut(c);
      	printOut(a);
      	return 0;
      }
      
      
      • 1