C语言——高精度除法

一、引子

1、引言

高精度除法相较于加减乘法更加复杂,它需要处理的因素更多,在这里我们先探讨高精度数除以低精度数,即大数除小数。这已满足日常所需,如需大数除以大数,可以使用专门的库,例如:

GNU Multiple Precision Arithmetic Library (GMP)

  • 这是最知名的任意精度数学库,提供了丰富的功能来处理整数、有理数和浮点数的高精度运算。

MPIR

  • 一个与GMP兼容的库,它被设计为GMP的直接替代品,在某些系统上可能提供更好的性能。

The GNU MPFR Library

  • 基于GMP构建,提供了严格圆整的多精度浮点运算能力。

使用这些库中的任何一个都需要你下载和链接到你的C程序中。这些库的文档通常会指导你如何将它们集成到你的项目中。集成后,你可以使用库提供的函数来执行高精度的整数和小数运算。

2、介绍

这里我们要实现大数除以小数,实际原理其实是模拟我们手算除法:

与高精度加减乘法不同的是,高精度除法是从高位开始运算,一步一步运算到最低位的,所以不用将被除数字符串反转。

二、核心算法

核心算法是由刚才的手算除法得来的,如下:

#define MAX 505
#define DECIMAL_PART 50//小数部分保留五十位
int i = 0;
int remainder = 0;
int high[MAX] = { 0 };
for (i = 0; i < high_len; i++)//高精度除法核心算法,模拟我们手算除法,从最高位开始除
{
	long long division = remainder * 10LL + high[i];//余数乘十,加上整数部分i位的数字作为被除数
	IntegerResult[i] = (int)division / low;//结果是被除数除以除数,这里是有余数的整数除法
	remainder = (int)division % low;//取余,下一步乘十后作为下一位的除数
}

for (i = 0; i < DECIMAL_PART + 1; i++)//小数部分计算,多计算一位,以便后面进行四舍五入
{
	remainder *= 10;//余数乘十作为被除数
	DecimalResult[i] = remainder / low;//计算小数部分i位的结果
	remainder %= low;//取余,下一步乘十后作为下一位的除数
}

核心算法分为两部分,一部分是求商的整数部分,一部分是求商的小数部分。

(1)商的整数部分代码是手动实现的长除法过程,模仿我们在纸上做除法时的步骤。这里使用数组high[]来表示高精度的被除数,low是低精度的除数,IntegerResult[]用来存储商的整数部分。

让我们逐步分析这段代码的工作原理:

  1. for循环:循环遍历高精度数high[]的每一位,从数字最高位开始进行运算。

  2. long long division = remainder * 10LL + high[i];

    • remainder是前一次除法后剩下的余数,初始化为0,因为我们从最高位开始除,最开始没有余数。
    • remainder * 10LL将余数乘以10,因为在长除法中,每向下一位,都相当于余数乘以10再加上新的一位。这里的10LL是一个long long类型的常量,确保运算结果能够存储在long long类型变量中,以避免溢出。
    • + high[i]是将当前处理的这一位数加到余数乘以10之后的值上,形成新的被除数。
  3. IntegerResult[i] = division / low;

    • 这行代码执行实际的除法运算。division是新的被除数,low是除数,计算出的商被存储在结果数组IntegerResult[i]的当前位置。
  4. remainder = division % low;

    • 这里计算新的余数,为下一位计算做准备。division % low计算了division除以low之后的余数。

循环中的每次迭代都处理高精度数的一位,并将其与前一位剩下的余数结合起来,进行除法运算。最终,这个for循环会填满整个IntegerResult[]数组,数组中的每个元素都是对应位上的商。

这个过程一直继续,直到所有的高精度数位都被处理完毕。我们通过不断将余数乘以10并加上下一位来逐位处理整个高精度数,这与手工执行长除法的过程相同。最后得到的IntegerResult[]数组就是除法操作的结果,而循环结束后剩下的remainder就是最终的余数。

(2)商的小数部分代码依旧是手动实现的长除法过程,模仿我们在纸上做除法时的步骤。这里使用remainder来除以lowDecimalResult[]用来存储商的小数部分。

接着我们逐步分析这段代码的工作原理:

  1. for循环:保留50位小数,多计算一位,为了后面的四舍五入,从数字最高位开始进行运算。

  2. remainder *= 10;

    • remainder整数商计算好后的余数,乘十后作为被除数,因为原被除数小数部分为0,所以相对于商的整数部分不用加其他的。
  3. DecimalResult[i] = remainder / low;

    • 这行代码执行实际的除法运算。remainder是新的被除数,low是除数,计算出的商被存储在结果数组DecimalResult[i]的当前位置。
  4. remainder %= low;

    • 这里计算新的余数,为下一位计算做准备。remainder %= low;计算了remainder除以low之后的余数。

最后商的小数部分也就求出了。

三、代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX 505
#define DECIMAL_PART 50//小数部分保留五十位

void StringTranstoDigit(char numch[], int num[],int length)//字符数组转成整型数组
{
	int i = 0;
	for (i = 0; i < length; i++)
	{
		num[i] = numch[i] - '0';
	}
}

void highDivLow(char highch[], int high_len, int low, int IntegerResult[],int DecimalResult[])//高精度除法
{
	if (low == 0)//除数为零的情况
	{
		fprintf(stderr,"divisor can not be zero!\n");//输出错误信息
		exit(EXIT_FAILURE);//退出程序,运行过程中失败
	}
	int i = 0;
	int remainder = 0;
	int high[MAX] = { 0 };

	StringTranstoDigit(highch,high,high_len);//字符转整型

	for (i = 0; i < high_len; i++)//高精度除法核心算法,模拟我们手算除法,从最高位开始除
	{
		long long division = remainder * 10LL + high[i];//余数乘十,加上整数部分i位的数字作为被除数
		IntegerResult[i] = (int)division / low;//结果是被除数除以除数,这里是有余数的整数除法
		remainder = (int)division % low;//取余,下一步乘十后作为下一位的除数
	}

	for (i = 0; i < DECIMAL_PART + 1; i++)//小数部分计算,多计算一位,以便后面进行四舍五入
	{
		remainder *= 10;//余数乘十作为被除数
		DecimalResult[i] = remainder / low;//计算小数部分i位的结果
		remainder %= low;//取余,下一步乘十后作为下一位的除数
	}

	if (DecimalResult[DECIMAL_PART] >= 5)//四舍五入
	{
		DecimalResult[DECIMAL_PART - 1]++;
	}
	for (i = DECIMAL_PART; i > 0; i--)//处理四舍五入后的进位,小数部分进位
	{
		int carry = 0;
		carry = DecimalResult[i] / 10;
		DecimalResult[i] %= 10;
		DecimalResult[i - 1] += carry;
	}
	if (DecimalResult[0] >= 10)//小数进整数位
	{
		IntegerResult[high_len - 1] = DecimalResult[0] / 10;
		DecimalResult[0] %= DecimalResult[0];
	}
}

void Print(int num[],int numdec[],int length)//打印整数和小数部分
{
	int i = 0;
	while (i < length - 1 && num[i] == 0)//去除前导零
	{
		i++;
	}
	for (; i < length ; i++)//打印整数部分
	{
		printf("%d",num[i]);
	}
	printf(".");//小数点
	for (i = 0; i < DECIMAL_PART; i++)//打印小数部分
	{
		printf("%d",numdec[i]);
	}
}

int main()
{
	char high[MAX] = { 0 };//高精度数,被除数
	scanf("%s",high);

	int low = 0;//低精度数,除数
	scanf("%d",&low);


	int IntegerResult[MAX] = { 0 };//结果整数部分
	int DecimalResult[DECIMAL_PART + 1] = { 0 };//结果小数部分

	int high_len = (int)strlen(high);//被除数长度

	highDivLow(high, high_len, low, IntegerResult,DecimalResult);//高精度除法

	Print(IntegerResult,DecimalResult,high_len);//打印
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/266344.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3.Redis持久化

文章目录 RDB&#xff08;Redis DataBase&#xff09;&#xff1a;RDB是什么&#xff1f;RDB能干嘛&#xff1f;RDB自动触发RDB手动触发RDB优点RDB缺点什么情况会触发RDB快照 AOF&#xff08;Append Only File&#xff09;&#xff1a;AOF是什么&#xff1f;AOF能干嘛&#xff…

【Hadoop】 YARN 运行过程/YARN设计目标

YARN 运行过程剖析YARN设计目标 YARN 运行过程剖析 一个Job在YARN中的处理过程&#xff1a; 客户端向RM提交一个job&#xff0c;进入RM中的调度器队列以供调度RM中的AppManager与NM协商协商好一个容器&#xff0c;以启动一个App Master实例App Master启动之后向RM注册并根据Jo…

刷题第五十一天 84. 柱状图中最大矩形

好难&#xff0c;看解析&#xff1a; # 双指针 class Solution:def largestRectangleArea(self, heights: List[int]) -> int:size len(heights)# 两个DP数列储存的均是下标indexmin_left_index [0] * sizemin_right_index [0] * sizeresult 0# 记录每个柱子的左侧第一…

量化服务器 - 后台挂载运行

服务器 - 后台运行 pip3命令被kill 在正常的pip命令后面加上 -no-cache-dir tmux 使用教程 https://codeleading.com/article/40954761108/ 如果你希望在 tmux 中后台执行一个 Python 脚本&#xff0c;你可以按照以下步骤操作&#xff1a; 启动 tmux: tmux这将会创建一个新…

Ubuntu 常用命令之 ps 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 ps命令是Linux下的一个非常重要的命令&#xff0c;它用于查看系统中的进程状态。ps是Process Status的缩写&#xff0c;可以显示系统中当前运行的进程的状态。 以下是一些常用的参数 a&#xff1a;显示所有进程&#xff08;包括…

【机器学习】决策树

参考课程视频&#xff1a;https://www.icourse163.org/course/NEU-1462101162?tid1471214452 1 概述 样子&#xff1a; 2 分裂 2.1 分裂原则 信息增益 信息增益比 基尼指数 3 终止 & 剪枝 3.1 终止条件 无需分裂 当前节点内样本同属一类 无法分裂 当前节点内…

【数据结构】四、串

目录 一、定义 二、表示与实现 定长顺序存储 堆分配存储 链式存储 三、BF算法 四、KMP算法 1.求next数组 方法一 方法二&#xff08;考试方法&#xff09; 2.KMP算法实现 方法一 方法二 3.nextval 4.时间复杂度 本节最重要的就是KMP算法&#xff0c;其他要求不高…

融资项目——swagger2的注解

1. ApiModel与ApiModelProperty(在实体类中使用) 如上图&#xff0c;ApiModel加在实体类上方&#xff0c;用于整体描述实体类。ApiModelProperty(value"xxx",example"xxx")放于每个属性上方&#xff0c;用于对属性进行描述。swagger2网页上的效果如下图&am…

c++内存池项目

文章目录 一、内存池介绍二、ThreadCache实现三、CentralCache实现四、PageCache实现五、回收内存六、大于256KB的内存申请与释放七、将new和delete换为定长内存池八、多线程环境下对比malloc进行基准测试九、使用基数树进行性能优化 一、内存池介绍 二、ThreadCache实现 下面…

Wordpress插件WP-Statistics无法识别来访IP国家和城市处理方法

Wordpress插件WP-Statistics&#xff0c;可以识别网站访问者的IP物理地址&#xff0c;统计出城市、国家&#xff0c;但最近发现都显示unknown/未知&#xff1a; 更新GeoIP数据库到最新还是不行&#xff1a; 偶然找到了之前能用的数据库&#xff0c;恢复回去&#xff0c;竟然大…

基于SpringBoot的桃花峪滑雪场租赁系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设计3.1 教练表3.2 教练聘请表3.3 押金规则表3.4 器材表3.5 滑雪场表3.7 售票表3.8 器材损坏表 四、系统展示五、核心代码5.1 查询教练5.2 教练聘请5.3 查询滑雪场5.4 滑雪场预定5.5 新…

【AI提示词人物篇】创新艺术未来,让科技改变想象空间

AI 绘画学习难度和练习技巧 学习绘画的技巧 学习能难度&#xff1a; 外貌特征&#xff1a;AI需要学习识别和理解各种外貌特征&#xff0c;如发型、肤色、眼睛颜色等。这可能需要大量的训练数据和复杂的模型架构。 镜头提示&#xff1a;AI需要学习理解不同镜头提示的含义&…

中心性算法归纳

中心性算法不仅是在我所学习的计算机网络当中起很重要的作用&#xff0c;在交通网络、社交网络、信息网络、神经网络当中也有很多的应用例子。今天我在这里总结一下场景的几种中心性算法。 参考文献 Python NetworkX库 偏心中心性&#xff08;Eccentricity Centrality&#x…

Kubernetes 的用法和解析(K8S 日志方案) -- 8

一、统一日志管理的整体方案 通过应用和系统日志可以了解Kubernetes集群内所发生的事情&#xff0c;对于调试问题和监视集群活动来说日志非常有用。对于大部分的应用来说&#xff0c;都会具有某种日志机制。因此&#xff0c;大多数容器引擎同样被设计成支持某种日志机制。 对…

安装vcpkg管理opencv的安装+MFC缺失的解决

第一步&#xff0c;出现#include没有办法找到opencv头文件的问题&#xff0c;无法解决 在VC的提示下&#xff0c;安装了vcpkg&#xff0c;然后用vcpkg命令来帮助安装opencv&#xff0c;过程十分顺利。 1. cmd 到命令行窗口&#xff1b; 2. 建立src文件夹&#xff0c;并进入…

KMP入门级别算法详解--终于解决了(next数组详解)

对于正常的字符串模式匹配&#xff0c;主串长度为m&#xff0c;子串为n&#xff0c;时间复杂度会到达O&#xff08;m*n&#xff09;&#xff0c;而如果用KMP算法&#xff0c;复杂度将会减少线型时间O&#xff08;mn&#xff09;。 设主串为ptr"ababaaababaa";&#…

MFC窗体背景颜色的设置、控件白色背景问题、控件文本显示重叠问题、被父窗体背景覆盖的问题

文章目录 设置mfc窗体背景颜色窗体设置背景颜色后解决控件白色背景解决重复修改控件文本后重叠的问题自绘控件被父窗体背景覆盖的问题 设置mfc窗体背景颜色 设置窗体的背景颜色非常简单&#xff0c;只需要在窗体的OnEraseBkgnd里面填充窗体背景就可以了&#xff0c;甚至直接画…

【SpringCloud】-GateWay源码解析

GateWay系列 【SpringCloud】-GateWay网关 一、背景介绍 当一个请求来到 Spring Cloud Gateway 之后&#xff0c;会经过一系列的处理流程&#xff0c;其中涉及到路由的匹配、过滤器链的执行等步骤。今天我们来说说请求经过 Gateway 的主要执行流程和原理是什么吧 二、正文 …

30. MVC设计模式

JavaEE 开发流程 ↓MVC的概念 MVC是Model-View-Controller的简称&#xff0c;即模型-视图-控制器。 MVC是一种设计模式&#xff0c;它把应用程序分成三个核心模块&#xff1a;模型、视图、控制器&#xff0c;它们各自处理自己的任务。 模型(model) 模型是应用程序的主体部分…

JavaEE进阶学习:Spring MVC 程序开发

1.什么是 Spring MVC Spring Web MVC 是基于Servlet API 构建的原始 Web 框架&#xff0c;从一开始就包含在Spring 框架中。它的正式名称 “Spring Web MVC” 来自其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为“Spring MVC”。 从上述定义我们可以得出两个关键信…