为什么需要高精度计算

对于 C++ 而言,最大的数据为 long long(64b,8位),对于超过 8B 的数据,C++ 没有对应的数据类型进行表示。所以我们需要知道高精度计算。更详细的解释,可以参考这个网页https://blog.csdn.net/justidle/article/details/104414459。

高精度除法计算原理

在读小学时,我们做除法都采用竖式方法计算。被除数从高位开始,和除数对齐,逐位“试商”,“试商”后除数减去“试商”的数的乘积,如下图所示。

采用计算机做高精度除法时,模拟日常除法的步骤。但计算机不可能做“试商”,这时,我们可以采用减法来模拟。

试商过程

1、将除数移动和被除数对齐,位数不够时,补 0。

2、利用被除数减去除数,一直减到被除数小于除数,减的次数,就是“试商”的结果,每移动一次。

3、重复上述步骤,一直到被除数和除数的位数相等为止。

举例说明

举一个例子,比如 524134 除以 123,结果是 4261 ,余数为 31。

1、第一位 4 的来源是我们把 524 和 123 对齐,然后进行循环减法,循环了 4 次,余 32;

2、将 32134 的前三位 321 继续和 123 对齐,循环减法 2 次,余 75;

3、把 7534 的前三位 753 和 123 对齐,循环减法 6 次,余 15;

4、将 154 和 123 对齐,只能减 1 次,余 31。

所以 524134 除以 123,结果是 4261,余数为 31。

计算过程

  A B 余数
1 524134 123 4 32
2 032134 0123 2 75
3 007534 00123 6 15
4 000154 000123 1 31
5 000031 0000123   31

高精度除法实现

思路

1、定义存储数组。

2、读入数据处理。

3、试商过程。

4、删除前导 0 。所谓前导零,就是出现类似这样数据 01234,这个 0 实际是不需要的。

5、输出结果。倒序输出减法的结果数组 C,因为我们的个位是存储在下标为 0 的地方。

技术细节说明

定义存储数组

根据题目的要求定义数组。这个部分代码如下:

const int MAXN = 1e5+4; //根据题目的最大值。+4为了防止A+B出现进位
char s1[MAXN] = {};//存储字符串
char s2[MAXN] = {};//存储字符串
int a[MAXN] = {};//存储被除数
int b[MAXN] = {};//存储除数B
int c[MAXN] = {};//存储商
int tmp[MAXN] = {};

注意:这里的数组索引 0 所在的数据表示本数据的长度。

辅助函数

比较大小函数

用于比较两个 int 类型数组内数据大小。返回值和 C++ 库函数 campare() 相同。

int compare(int a[], int b[]) {//索引为0的数据为数组长度if (a[0]>b[0]) {return 1;} else if (a[0]<b[0]) {return -1;}//逐位比较for (int i=a[0]; i>0; i--) {if (a[i]>b[i]) {return 1;} else if (a[i]<b[i]) {return -1;}}return 0;
}

移位操作函数

void numcpy(int a[],int b[],int dest) {//将数组右移,使两个数组右端对齐,形参q数组储存右移后的结果for (int i=1;i<=a[0];i++) {b[i+dest-1] =a[i];}b[0] = a[0]+dest-1;
}

读入数据并处理

这里我们先考虑以下几种情况,即 15/4=3 ... 3、-8/3=-2 ... -2、10/(-3)=-3 ... 1 或者 -3/(-2)=1 ... -1,也就是说,需要对输入数据的正负号进行判断。这个部分代码如下:

    scanf("%s %s", s1, s2);//读入字符串//处理负数bool flaga = false;//乘数a的符号if ('-'==s1[0]) {flaga = true;strcpy(s1, &s1[1]);//删除负号}bool flagb = false;//乘数b的符号if ('-'==s2[0]) {flagb = true;strcpy(s2, &s2[1]);//删除负号}//处理输出的负号if (true==flaga && false==flagb) {//商为负数printf("-");}//处理乘数1int len = strlen(s1);a[0] = len;for (int i=0; i<len; i++) {a[len-i]=s1[i]-'0';}//处理乘数2len = strlen(s2);b[0] = len;for (int i=0; i<len; i++) {b[len-i]=s2[i]-'0';}

试商

这个部分代码如下:

    if (0==compare(a,b)) {//两数相等printf("1\n0\n");return 0;} else if (-1==compare(a,b)) {//被除数小,除数大printf("0\n");//输出除数if (true==flaga) {printf("-");}printf("%s\n", s1);return 0;} else {c[0] = a[0]-b[0]+1;for (int i=c[0]; i>0; i--) {memset(tmp, 0, sizeof(tmp));//高位对齐numcpy(b,tmp,i);//while (compare(a, tmp)>=0) {c[i]++;//减法for (int j=1; j<=a[0]; j++) {if (a[j]<tmp[j]) {a[j+1]--;a[j]+=10;}a[j]-=tmp[j];}int k=a[0];while (a[k]==0) {k--;}a[0]=k;}}//控制最高位的0while (c[0]>0 && c[c[0]]==0) {c[0]--;}}

输出计算结果

采用倒序的方式输出,因为我们数据保存是倒序结构,也就

    //逆序打印输出商和余数for (int i=c[0]; i>0; i--) {printf("%d", c[i]);}printf("\n");if (0==a[0]) {printf("0\n");} else {if (true==flaga) {printf("-");}for (int i=a[0]; i>0; i--) {printf("%d", a[i]);}printf("\n");}

输出格式需要根据实际题目要求进行修改。

例题和 AC 代码

题目

题目链接

一本通 OJ:http://ybt.ssoier.cn:8088/problem_show.php?pid=1308。

我的OJ:http://47.110.135.197/problem.php?id=1213。

题目描述

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

输入

输入两个低于300位的正整数。

输出

输出商和余数。

样例输入

1231312318457577687897987642324567864324567876543245671425346756786867867867
1231312318767141738178325678412414124141425346756786867867867

样例输出

999999999748590
179780909068307566598992807564736854549985603543237528310337

分析

题目告诉我们不超过 300 位,也就是 MAXN = 300+4。

A 代码

#include <bits/stdc++.h>
using namespace std;const int MAXN = 300+4; //根据题目的最大值。+4为了防止A+B出现进位
char s1[MAXN] = {};//存储字符串
char s2[MAXN] = {};//存储字符串
int tmp[MAXN] = {};//交换用字符串
int a[MAXN] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[MAXN] = {};//存储和Bint compare(int a[], int b[]) {//索引为0的数据为数组长度if (a[0]>b[0]) {return 1;} else if (a[0]<b[0]) {return -1;}//逐位比较for (int i=a[0]; i>0; i--) {if (a[i]>b[i]) {return 1;} else if (a[i]<b[i]) {return -1;}}return 0;
}void numcpy(int a[],int b[],int dest) {//将数组右移,使两个数组右端对齐,形参q数组储存右移后的结果for (int i=1;i<=a[0];i++) {b[i+dest-1] =a[i];}b[0] = a[0]+dest-1;
}int main() {scanf("%s %s", s1, s2);//读入字符串//处理负数bool flaga = false;//乘数a的符号if ('-'==s1[0]) {flaga = true;strcpy(s1, &s1[1]);//删除负号}bool flagb = false;//乘数b的符号if ('-'==s2[0]) {flagb = true;strcpy(s2, &s2[1]);//删除负号}//处理输出的负号if (true==flaga && false==flagb) {//商为负数printf("-");}//处理乘数1int len = strlen(s1);a[0] = len;for (int i=0; i<len; i++) {a[len-i]=s1[i]-'0';}//处理乘数2len = strlen(s2);b[0] = len;for (int i=0; i<len; i++) {b[len-i]=s2[i]-'0';}if (0==compare(a,b)) {//两数相等printf("1\n0\n");return 0;} else if (-1==compare(a,b)) {//被除数小,除数大printf("0\n");//输出除数if (true==flaga) {printf("-");}printf("%s\n", s1);return 0;} else {c[0] = a[0]-b[0]+1;for (int i=c[0]; i>0; i--) {memset(tmp, 0, sizeof(tmp));//高位对齐numcpy(b,tmp,i);//while (compare(a, tmp)>=0) {c[i]++;//减法for (int j=1; j<=a[0]; j++) {if (a[j]<tmp[j]) {a[j+1]--;a[j]+=10;}a[j]-=tmp[j];}int k=a[0];while (a[k]==0) {k--;}a[0]=k;}}//控制最高位的0while (c[0]>0 && c[c[0]]==0) {c[0]--;}}//逆序打印输出商和余数for (int i=c[0]; i>0; i--) {printf("%d", c[i]);}printf("\n");if (0==a[0]) {printf("0\n");} else {if (true==flaga) {printf("-");}for (int i=a[0]; i>0; i--) {printf("%d", a[i]);}printf("\n");}return 0;
}

C++ 的高精度除法相关推荐

  1. 中石油-高精度除法-java版

    问题 G: [高精度]高精度数除以低精度数I 时间限制: 1 Sec  内存限制: 512 MB 提交: 19  解决: 15 [提交][状态][讨论版] 题目描述 修罗王聚集了庞大的暗元素以施展隐匿 ...

  2. 基础算法 —— 高精度计算 —— 高精度除法

    [高精除以低精] 1.算法分析 做除法时,每一次的商的值都在0~9,每次求得的余数连接以后的若干位得到新的被除数,继续做除法.因此在做高精度除法时,要涉及到乘法运算和减法运算以及移位处理. 为程序简洁 ...

  3. 国王游戏(贪心 + 高精度乘法 + 高精度除法 + 高精度比较大小)

    题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏. 首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数. 然后,让这 n 位大臣排成一排,国王站在队伍 ...

  4. (压位)高精度乘法,高精度加法,高精度减法,高精度除法

    大值 乘 大值: 题目链接:https://www.luogu.com.cn/problem/P1303 # include <iostream> # include <string ...

  5. bigdicmal除法精度设置_使用java求高精度除法,要求保留N位小数

    题目要求是高精度除法,要求保留N位小数(四舍五入),并且当整数部分为0时去除0的显示 import java.math.BigDecimal; import java.util.Scanner; pu ...

  6. 高精度除法(精确到小数点后N位)

    这种类型的高精度除法颇为简单,直接贴上代码 //写在前面 //对于精确到小数点后任意位数的高精度除法 //只要简单的模拟除法过程就可 //在直接用除法算出小数点前的整数后 //改变被除数 a=(a%b ...

  7. 高精度除法算法(大数除于小数)

    高精度除法(大数除于小数) 思想:和人一样,人是从高位除,得出结果.但有点不一样的是每次除于之后的余数,如果高位后面还有数没有数的话,需要把余数乘于10,再加上下一位数.继续后面的运算,最后再把前置的 ...

  8. C++ 大整数运算 高精度除法

    前言 这篇文章主要是对于大整数类的设计过程中,如何实现并改进长除法(模拟竖式法)的一个总结. 高精度除法的分类和比较 虽然有些文章在讨论大整数的除法运算时,喜欢分成高精度除以高精度和高精度除以低精度( ...

  9. 高精度除法的介绍以及模板的分享

    今天我们来介绍一下高精度除法 什么是高精度除法呢? 我们来看看百度百科是怎么介绍高精度除法的,但是并没有搜到相关信息,逛了一圈发现也没人介绍,那我在这里就简单提一下. 一般我们计算高精度除法分为高精度 ...

最新文章

  1. UI之UI View--属性及用法
  2. jenkins执行shell脚本,找不到环境变量
  3. 吴恩达 coursera AI 专项四第二课总结+作业答案
  4. [云炬创业基础笔记]第二章创业者测试6
  5. jasperreports_JasperReports:棘手的部分
  6. [Unity] ACT 战斗系统学习 4:重构前的第三人称控制器
  7. 那年我整理的SE面试题
  8. seconds_behind_master入门
  9. 105.输出控制缓存
  10. Verilog设计实例(1)线性反馈移位寄存器(LFSR)
  11. 文本特征提取之TF-IDF算法(原理+Python代码)
  12. 基于STM32CubeIDE的STM32H750 DCMI接口驱动OV2640读取JPEG结合自编上位机实现可以用的数字图传
  13. 商城项目 ------ 订单的生成功能(vue实现)
  14. drop index mysql_MySQL修改和删除索引(DROP INDEX)
  15. PHP执行底层机制-zend详解
  16. 【文献阅读】RL经典:Benchmarking Deep Reinforcement Learning for Continuous Control
  17. 教你用 Python 快速批量转换 HEIC 文件
  18. 【iMessage苹果推群发】苹果相册推它由pushchatkey.pem和pushchatcert.pem作为单独的文件使用
  19. 狼、羊、菜、农夫过河问题 穷举 Python实现
  20. html网站手机最小字体大小,html在手机浏览器如何设置字体大小

热门文章

  1. The missing quarter of a million 消失的25万 | 经济学人20230311版社论高质量双语精翻
  2. CentOS关机和重启命令
  3. Linux使用原生迅雷
  4. 简单认识Samba服务以及Linux操作系统下部署案例解析
  5. 淘宝、天猫API大全,SKU信息,商品详情调用展示
  6. Uni-app学习过程(1)
  7. Axure可视化动态数据图表6合1元件库
  8. Visual Studio工具集相关(MSBuild)
  9. 关于vim gf问题
  10. Android背景色渐变(左上-右下)