C语言实现高精度除高精度

大一小白尝试高精度除高精度

引言

笔者是一位大一学生,在做题的过程中接触到了高精度除法,写下这篇博客帮助理清思路。希望这篇博客能够帮助到更多刚接触C语言的同学们。如果文中有错误,欢迎指正。

一、什么是高精度除法

高精度除法就是对于普通数据类型无法表示的大整数进行除法运算。

二、为什么需要高精度除法

在C语言中,常用的数据类型有int, long long, double等,但是这些数据类型的大小有限,当输入的数据过大,这些数据类型就无法实现其功能,强行使用可能会出现错误。在这种情况下,我们需要高精度除法来完成运算。

三、高精度除法的实现方式

思路

参考高精度乘法的思路,首先我们知道电脑笨笨的,其次我们知道可以回到小学寻求答案,于是高精度除法的实现思路就十分清晰了。那就是模拟手动运算除法的方式,也就是说,我们要通过竖式除法运算达到高精度运算的目的。

数据类型

与高精度乘法相类似的,我们选择字符串来存储很大很大的一些整数(真是太可恶了!)

竖式除法复习

这里我们只看整数的除法法则

1)从被除数的高位起,先看除数有几位,再用除数试除被除数的前几位,如果它比除数,再试除多一位数;

2)除到被除数的哪一位,就在那一位上面写上商;

3)每次除后余下的数必须比除数小

实现步骤

1.输入
2.试除(比大小移位)
3.结束
4.输出

准备工作
void High_Precision_Division(char c_dividend[], char c_divisor[], char c_quotient[]) {
	int i;
	int i_dividend[Number_Size];//被除数
	int i_divisor[Number_Size];//除数
	int i_quotient[Number_Size];//商
	char temp_answer[Number_Size];
	int start;
	int flag;
	int length_temp_answer;
	int length_divisor = strlen(c_divisor);
	int length_dividend = strlen(c_dividend);
	memset(c_quotient, 0, length_quotient);
	memset(i_dividend, 0, sizeof(i_dividend));
	memset(i_divisor, 0, sizeof(i_divisor));
	memset(i_quotient, 0, sizeof(i_quotient));
	memset(temp_answer, 0, sizeof(temp_answer));//完成初始化
	if (Size_Comparison(c_dividend, length_dividend, c_divisor, length_divisor) < 0) {
		c_quotient[0] = '0';
		return;
	}
	start = 0;
}
进行试除

我们知道,试除的过程实际上就是比大小,如果不够大则移动一位,如果够大则算出商。为了方便,我们这里引入一个比大小的函数。

int Size_Comparison(char str_1[], int length_1, char str_2[], int length_2) {
	int i;
	if (length_1 < length_2) {
		return -1;
	}
	else if (length_1 > length_2) {
		return 1;
	}
	else {
		for (i = 0; i < length_1; i++) {
			if (str_1[i] < str_2[i]) {
				return -1;
			}
			else if (str_1[i] > str_2[i]) {
				return 1;
			}
		}
		return 0;
	}
}

这个函数传入两个char*,两个int,若返回-1则第一个小,返回1则第一个大,返回0则相等。
现在为了能够算出商,我们需要引入高精度减法的函数。试除的数能减几次,商就是几。

	//start代表的是被除数试除的起始位置
	while (length_dividend - start >= length_divisor) {
		if (length_dividend - start == length_divisor && Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {
			break;
		}
		//如果剩下的数不够除了(长度相等而小于)就退出循环
		if (Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {
			//长度足够但是同位数时不够,就向后借一位
			i_quotient[start + length_divisor]++;//对应位置商加一
			High_Precision_Subtraction(&c_dividend[start], length_divisor + 1, c_divisor, length_divisor, temp_answer, 1, &flag);
			//从对应位置减去除数
			length_temp_answer = strlen(temp_answer);
			//temp_answer里面存储的是差
			memset(&c_dividend[start], 0, sizeof(char) * (length_divisor + 1));
			start = start + length_divisor + 1 - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			//这一段完成的是拷贝,当然也可以用函数,之后会进行优化
			memset(temp_answer, 0, sizeof(temp_answer));
		}
		else {//与上一段同理,长度相同时可以继续,就直接作差
			i_quotient[start + length_divisor - 1]++;
			High_Precision_Subtraction(&c_dividend[start], length_divisor, c_divisor, length_divisor, temp_answer, 1, &flag);
			length_temp_answer = strlen(temp_answer);
			memset(&c_dividend[start], 0, sizeof(char) * length_divisor);
			start = start + length_divisor - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			memset(temp_answer, 0, sizeof(temp_answer));
		}
	}
	//完成除的过程
处理商

首先将多余的0除去,在这里是前导零,然后转换回字符串

	for (i = 0; i < length_dividend; i++) {
		if (i_quotient[i]) {
			start = i;
			break;
		}
	}
	length_quotient = length_dividend - start;
	for (i = start; i < length_dividend; i++) {
		c_quotient[i - start] = i_quotient[i] + '0';
	}
	//处理商并输出
全部代码
void High_Precision_Division(char c_dividend[], char c_divisor[], char c_quotient[], int length_quotient) {
	int i;
	int i_dividend[Number_Size];//被除数
	int i_divisor[Number_Size];//除数
	int i_quotient[Number_Size];//商
	char temp_answer[Number_Size];
	int start;
	int flag;
	int length_temp_answer;
	int length_divisor = strlen(c_divisor);
	int length_dividend = strlen(c_dividend);
	memset(c_quotient, 0, length_quotient);
	memset(i_dividend, 0, sizeof(i_dividend));
	memset(i_divisor, 0, sizeof(i_divisor));
	memset(i_quotient, 0, sizeof(i_quotient));
	memset(temp_answer, 0, sizeof(temp_answer));//完成初始化
	if (Size_Comparison(c_dividend, length_dividend, c_divisor, length_divisor) < 0) {
		c_quotient[0] = '0';
		return;
	}
	start = 0;
	while (length_dividend - start >= length_divisor) {
		if (length_dividend - start == length_divisor && Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {//如果剩下的数不够除了就退出循环
			break;
		}
		if (Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {//长度足够但是同位数时不够,就向后借一位
			i_quotient[start + length_divisor]++;//对应位置商加一
			High_Precision_Subtraction(&c_dividend[start], length_divisor + 1, c_divisor, length_divisor, temp_answer, 1, &flag);
			length_temp_answer = strlen(temp_answer);
			memset(&c_dividend[start], 0, sizeof(char) * (length_divisor + 1));
			start = start + length_divisor + 1 - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			memset(temp_answer, 0, sizeof(temp_answer));
		}
		else {
			i_quotient[start + length_divisor - 1]++;
			High_Precision_Subtraction(&c_dividend[start], length_divisor, c_divisor, length_divisor, temp_answer, 1, &flag);
			length_temp_answer = strlen(temp_answer);
			memset(&c_dividend[start], 0, sizeof(char) * length_divisor);
			start = start + length_divisor - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			memset(temp_answer, 0, sizeof(temp_answer));
		}
	}
	//完成除的过程
	for (i = 0; i < length_dividend; i++) {
		if (i_quotient[i]) {
			start = i;
			break;
		}
	}
	length_quotient = length_dividend - start;
	for (i = start; i < length_dividend; i++) {
		c_quotient[i - start] = i_quotient[i] + '0';
	}
	//处理商并输出
	return;
}

四、结语

这个函数使用的实际上是减法,因此在时间复杂度上是非常高的,处理很小的除数除很大的被除数十分容易超时,后续会对除数这一块进行优化。十分感谢各位的阅读!

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言实现高精度除法高精度除以高精度)可以通过字符串和数组来实现。下面是一个示例代码: ```c #include <stdio.h> #include <string.h> #define MAX_LEN 1000 void divide(char dividend[], char divisor[], char quotient[]) { int len1 = strlen(dividend); int len2 = strlen(divisor); int i, j, k; // 将被除数和除数转换为整型数组 int num1[MAX_LEN], num2[MAX_LEN]; for (i = 0; i < len1; i++) { num1[i] = dividend[i] - '0'; } for (i = 0; i < len2; i++) { num2[i] = divisor[i] - '0'; } // 初始化商和余数 int result[MAX_LEN], remainder[MAX_LEN]; memset(result, 0, sizeof(result)); memset(remainder, 0, sizeof(remainder)); // 从高位到低位进行除法运算 for (i = 0; i < len1; i++) { // 将余数左移一位,加上当前位的数字 for (j = len2 - 1; j >= 0; j--) { remainder[j + 1] = remainder[j]; } remainder[0] = num1[i]; // 计算当前位的商 for (j = 0; j < 10; j++) { if (compare(remainder, num2, len2) >= 0) { subtract(remainder, num2, len2); result[i]++; } else { break; } } } // 将商转换为字符串 int len = 0; for (i = 0; i < len1; i++) { if (result[i] != 0) { break; } } for (; i < len1; i++) { quotient[len++] = result[i] + '0'; } quotient[len] = '\0'; } int compare(int num1[], int num2[], int len) { for (int i = 0; i < len; i++) { if (num1[i] > num2[i]) { return 1; } else if (num1[i] < num2[i]) { return -1; } } return 0; } void subtract(int num1[], int num2[], int len) { for (int i = len - 1; i >= 0; i--) { if (num1[i] < num2[i]) { num1[i] += 10; num1[i - 1]--; } num1[i] -= num2[i]; } } int main() { char dividend[MAX_LEN], divisor[MAX_LEN], quotient[MAX_LEN]; printf("请输入被除数:"); scanf("%s", dividend); printf("请输入除数:"); scanf("%s", divisor); divide(dividend, divisor, quotient); printf("商为:%s\n", quotient); return 0; } ``` 这段代码实现高精度除法,通过将被除数和除数转换为整型数组,然后从高位到低位进行除法运算,最后将商转换为字符串输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值