今天,我就来写一个关于高精度算法的总结,首先,我们要知道C++为什么要用到高精度算法,首先我们知道,C++中最大的整数类型就是long long ,最大范围是10的18次方,但是如果超过了10的18次方怎么办,存都存不下,更别谈运算了,这种数被称为高精度数和大整数!
先给大家说一下高精度的名词:
低精:
直接可以使用 C++ 中有的数据类型进行定义。比如 15,678,808,877 这个数,我们可以用 long long 来定义。
高精加高精:
高精度数加上高精度数。
高精乘高精:
高精度数乘上高精度数。
高精乘低精:
高精度数乘上低精度数。
高精除高精:
高精度数除以高精度数。
高精除低精:
高精度数除以低精度数。
高精度加法
接下来,我们就可以正式开始高精度运算了,我们先从高精度加法算起,我们在小学二三年级的时候,做一些加法题都需要用到竖式计算,而这种竖式计算是无论多大的数都可以算出来的,所以我们可以借助模拟竖式计算的方法来进行高精度加法运算。
思路:
-
定义存储数组。
-
读入数据到数组中。注意是倒序存放,也就是个位放在数组下标为 0 的地方。
-
从个位开始模拟竖式加法的过程,完成整个加法。
-
删除前导 0 。所谓前导零,就是出现类似这样数据 01234,这个 0 实际是不需要的。
-
输出加法的结果。倒序输出加法的结果数组 C,因为我们的个位是存储在下标为 0 的地方。
我们先来看一看存储结构:
const int N=1e5+10;
char s1[N]={};//存储字符串
char s2[N]={};//存储字符串
int a[N]={};//存储加数A
int b[N]={};//存储加数B
int c[N]={};//存储和C
读入数据:
我们先输入s1,s2两个字符串,然后再求出两个字符串的长度l1和l2,之后将s1[i]赋值给a[i],将s2[i]赋值给b[i],用int类型数组更容易计算一些!
scanf("%s %s",s1,s2);
int l1=strlen(s1);
int l2=strlen(s2);
for(int i=0;i<l1; i++)
a[i]=s1[l1-i-1]-'0';
for(int i=0;i<l2;i++)
b[i]=s2[l2-i-1]-'0';
模拟竖式加法:
首先,我们要将a[i]和b[i]加起来,存到c[i]里面,在将他们的进位存在jw里面,每次运算加上去,哪怕是0,之后再将c[i]对10来取模,是求进位过后这个位是什么数字!
//模拟竖式加法
int jw=0;//进位
int l=max(l1,l2)+1;//注意因为最高位可能出现进位
for(int i=0;i<len;i++)
{
c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
jw=c[i]/10;//本次加法是否存在进位
c[i]%=10;//只能保存0~9的数据
}
有两个细节需要注意:
-
进位如何保存;
-
最高位进位如何解决。
删除多余的0:
由于我们是倒着来的前面有很多多余的0,我们用for循环倒着删除,如果遇到0了,就将c[i]的长度减1,直到碰见第一个不是0的最高位,就break;结束删除!
//删除前导零
for (int i=l-1;i>=0;i--)
{
//因为我们是从下标0开始,所以最高位是保存在l-1
if(0==c[i]&&l>1)
{
//注意要有 l>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
len--;
}
else
{
//第一个不是零的最高位,结束删除
break;
}
}
输出计算结果:
最后就是将计算结果输出就行了,用for循环一个一个来打印!
//逆序打印输出
for (int i=l-1;i>=0;i--)
{
printf("%d",c[i]);
}
printf("\n");
高精度加法的完整代码:
#include <bits/stdc++.h>
using namespace std;
const int N=200+4;
char s1[N]={};//存储字符串
char s2[N]={};//存储字符串
int a[N]={};//存储加数A
int b[N]={};//存储加数B
int c[N]={};//存储和B
int main()
{
scanf("%s %s",s1,s2);//读入字符串A
//将字符串写入到数组A中
int l1=strlen(s1);
for(int i=0;i<l1;i++)
{
//倒序写入
a[i]=s1[len1-i-1]-'0';
}
//将字符串写入到数组A中
int l2=strlen(s2);
for(int i=0;i<len2;i++)
{
//倒序写入
b[i]=s2[len2-i-1]-'0';
}
//模拟竖式加法
int jw=0;//进位
int l=max(l1,l2)+1;//注意因为最高位可能出现进位
for(int i=0;i<l;i++)
{
c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
jw=c[i]/10;//本次加法是否存在进位
c[i]%=10;//只能保存 0 ~ 9 的数据
}
//删除前导零
for(int i=l-1;i>=0;i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if(0==c[i]&&len>1)
{
//注意要有 len>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
l--;
}
else
{
//第一个不是零的最高位,结束删除
break;
}
}
//逆序打印输出
for (int i=l-1; i>=0; i--)
{
printf("%d", c[i]);
}
printf("\n");
return 0;
}
高精度减法
高精度减法计算原理
在读小学时,我们做减法都采用竖式方法,如图 1 所示。这样,我们可以写出两个整数相减的算法。
编辑
我们就可以用 C++ 语言来模拟这个竖式减法的过程。我们可以考虑利用 C++ 的数组来存储对应数据,假设用数组 A 存储被减数 856 的每一位,具体来说就是 A1 存储个位 6,A2 存储十位 5,A3存储百位 8;类似数组 A 的结构,使用数组 B 存储减数 257;类似数组 A 的结构,使用数组 C 来存储对应的差 599。两数相加的结果就如图 2 所示。这样理论上来说,我们就可以计算无限大的数据。如上图 2 所示,下表表示对应的存储方式。
数组 A | 数组 B | 数组 C | |
[0] | 6 | 7 | 9 |
[1] | 5 | 5 | 9 |
[2] | 8 | 2 | 5 |
总结:利用数组存储,突破存储的限制。每个位置存储 0 ~ 9 之间的数据。
高精度减法实现
思路
1、定义存储数组。
2、被减数和减数确认。由于减法可能出现负数。
3、读入数据到数组中。注意:保证被减数大于减数;倒序存放,也就是个位放在数组下标为 0 的地方。
4、从个位开始模拟竖式减法的过程,完成整个减法。
5、删除前导 0 。所谓前导零,就是出现类似这样数据 01234,这个 0 实际是不需要的。
6、输出减法的结果。倒序输出减法的结果数组 C,因为我们的个位是存储在下标为 0 的地方。
技术细节说明
定义存储数组
根据题目的要求定义数组。这个部分代码如下:
const int MAXN = 1e5+4; //根据题目的最大值。+4为了防止A+B出现进位
char s1[MAXN] = {};//存储字符串
char s2[MAXN] = {};//存储字符串
char tmp[MAXN] = {};//交换用字符串
int a[MAXN] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[MAXN] = {};//存储和B
被减数和减数确认
由于减法可能出现负数,如 3-5=-2,我们在计算的时候,实际是使用 5-3=2,最后在结果前面添加负号。如果出现被减数小于减数的情况,要将两者颠倒。
scanf("%s %s", s1, s2);//读入字符串
int lena = strlen(s1);
int lenb = strlen(s2);
//判断最终的结果符号
if ((lena<lenb) || (lena==lenb && strcmp(s1,s2)<0)) {
//被减数小于减数,结果为负数
printf("-");
//交换数据
strcpy(tmp, s1);
strcpy(s1, s2);
strcpy(s2, tmp);
//更新长度数据
lena = strlen(s1);
lenb = strlen(s2);
}
读入数据到数组
利用读入字符串的方法读入数据,再倒序写入到对应的数组中。这个部分代码如下:
//将字符串写入到数组A中
for (int i=0; i<lena; i++) {
//倒序写入
a[i] = s1[lena-i-1] - '0';
}
//将字符串写入到数组B中
for (int i=0; i<lenb; i++) {
//倒序写入
b[i] = s2[lenb-i-1] - '0';
}
模拟竖式减法
有两个技术细节:如何判断发生借位。这个部分代码如下:
//模拟竖式减法
for (int i=0; i<lena; i++) {
if (a[i]<b[i]) {
//有借位
a[i+1]--;
a[i] += 10;
}
c[i] = a[i] - b[i];
}
删除前导零
因为减法运算可能会出现最高位为零,所以我们需要判断是否需要删除前导零。这个部分代码如下:
//删除前导零
for (int i=lena-1; i>=0; i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if (0==c[i] && lena>1) {
//注意要有 lena>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
lena--;
} else {
//第一个不是零的最高位,结束删除
break;
}
}
输出计算结果
采用倒序的方式输出,因为我们数据保存是倒序结构,也就是低位在前。
//逆序打印输出
for (int i=lena-1; i>=0; i--) {
printf("%d", c[i]);
}
printf("\n");
高精度减法的完整代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e4+4; //根据题目的最大值。+4为了防止A+B出现进位
char s1[MAXN] = {};//存储字符串
char s2[MAXN] = {};//存储字符串
char tmp[MAXN] = {};//交换用字符串
int a[MAXN] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[MAXN] = {};//存储和B
int main() {
scanf("%s %s", s1, s2);//读入字符串
int lena = strlen(s1);
int lenb = strlen(s2);
//判断最终的结果符号
if ((lena<lenb) || (lena==lenb && strcmp(s1,s2)<0)) {
//被减数小于减数,结果为负数
printf("-");
//交换数据
strcpy(tmp, s1);
strcpy(s1, s2);
strcpy(s2, tmp);
//更新长度数据
lena = strlen(s1);
lenb = strlen(s2);
}
//将字符串写入到数组A中
for (int i=0; i<lena; i++) {
//倒序写入
a[i] = s1[lena-i-1] - '0';
}
//将字符串写入到数组B中
for (int i=0; i<lenb; i++) {
//倒序写入
b[i] = s2[lenb-i-1] - '0';
}
//模拟竖式减法
for (int i=0; i<lena; i++) {
if (a[i]<b[i]) {
//有借位
a[i+1]--;
a[i] += 10;
}
c[i] = a[i] - b[i];
}
//删除前导零
for (int i=lena-1; i>=0; i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if (0==c[i] && lena>1) {
//注意要有 lena>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
lena--;
} else {
//第一个不是零的最高位,结束删除
break;
}
}
//逆序打印输出
for (int i=lena-1; i>=0; i--) {
printf("%d", c[i]);
}
printf("\n");
return 0;
}
高精度乘法
高精度乘法计算原理
在读小学时,我们做乘法都采用竖式方法,如图 1 所示。 这样,我们可以写出两个整数相减的算法。
编辑
我们就可以用 C++ 语言来模拟这个竖式减法的过程。我们可以考虑利用 C++ 的数组来存储对应数据,假设用数组 A 存储被减数 856 的每一位,具体来说就是 A1 存储个位 6,A2 存储十位 5,A3存储百位 8;类似数组 A 的结构,使用数组 B 存储减数 25;类似数组 A 的结构,使用数组 C 来存储对应的乘积 21400。两数相加的结果就如图 2 所示。这样理论上来说,我们就可以计算无限大的数据。如上图 2 所示,下表表示对应的存储方式。
数组 A | 数组 B | 数组 C | |
[0] | 6 | 5 | 0 |
[1] | 5 | 2 | 0 |
[2] | 8 | 4 | |
[3] | 1 | ||
[4] | 2 |
如上面的图 2 ,首先计算被乘数与乘数的个位数字的乘积,把结果保存到积数组中,然后再用被除数乘以乘数的十位数字,把结果退一位加到积数组中。每加一次乘积结果就进行一次进位处理,放在一个新组数里面。其方法与加法中的进位处理一样。
编辑
关键点
1、a[i]*b[j] 应该累加到 i+j 的位置;
2、累加总结果为: c[i+j] = a[i]*b[j]+jw+c[i+j];
3、所以每次累加完后:
1)带入下一位累加的进位: jw = c[i+j] / 10;
2)本位实际数: c[i+j] %= 10。
高精度乘法实现
思路
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] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[2*MAXN] = {};//存储乘积
读入数据并处理
这里我们先考虑以下几种情况,即 -3*5=-15 或者 -4*8=-32 或者 -3*(-2)=6,也就是说,需要对输入数据的正负号进行判断。这个部分代码如下:
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) || (false==flaga && true==flagb)) {
printf("-");
}
//处理乘数1
int lena = strlen(s1);
for (int i=0; i<lena; i++) {
a[lena-i-1]=s1[i]-'0';
}
//处理乘数2
int lenb = strlen(s2);
for (int i=0; i<lenb; i++) {
b[lenb-i-1]=s2[i]-'0';
}
模拟竖式乘法
这个部分代码如下:
//模拟竖式乘法
int jw;//上一轮计算进位
for (int i=0; i<lena; i++) {
jw=0;
for (int j=0; j<lenb; j++) {
//交叉乘积
c[i+j] = a[i]*b[j]+jw+c[i+j];//当前乘积+上次乘积进位+原数
jw = c[i+j]/10;//处理进位
c[i+j] %= 10;
}
c[i+lenb]=jw;//进位设置
}
删除前导零
这个部分代码如下:
//删除前导零
int lenc=lena+lenb;
for (int i=lenc-1; i>=0; i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if (0==c[i] && lenc>1) {
//注意要有 lenc>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
lenc--;
} else {
//第一个不是零的最高位,结束删除
break;
}
}
输出计算结果
采用倒序的方式输出,因为我们数据保存是倒序结构,也就是低位在前。
//逆序打印输出
for (int i=lenc-1; i>=0; i--) {
printf("%d", c[i]);
}
printf("\n");
高精度乘法代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200+4; //根据题目的最大值。+4为了防止A+B出现进位
char s1[MAXN] = {};//存储字符串
char s2[MAXN] = {};//存储字符串
int a[MAXN] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[2*MAXN] = {};//存储和B
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) || (false==flaga && true==flagb)) {
printf("-");
}
//处理乘数1
int lena = strlen(s1);
for (int i=0; i<lena; i++) {
a[lena-i-1]=s1[i]-'0';
}
//处理乘数2
int lenb = strlen(s2);
for (int i=0; i<lenb; i++) {
b[lenb-i-1]=s2[i]-'0';
}
//模拟竖式乘法
int jw;//上一轮计算进位
for (int i=0; i<lena; i++) {
jw=0;
for (int j=0; j<lenb; j++) {
//交叉乘积
c[i+j] = a[i]*b[j]+jw+c[i+j];//当前乘积+上次乘积进位+原数
jw = c[i+j]/10;//处理进位
c[i+j] %= 10;
}
c[i+lenb]=jw;//进位设置
}
//删除前导零
int lenc=lena+lenb;
for (int i=lenc-1; i>=0; i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if (0==c[i] && lenc>1) {
//注意要有 lenc>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
lenc--;
} else {
//第一个不是零的最高位,结束删除
break;
}
}
//逆序打印输出
for (int i=lenc-1; i>=0; i--) {
printf("%d", c[i]);
}
printf("\n");
return 0;
}
高精度除法
高精度除法计算原理
在读小学时,我们做除法都采用竖式方法计算。被除数从高位开始,和除数对齐,逐位“试商”,“试商”后除数减去“试商”的数的乘积,如下图所示。
编辑
采用计算机做高精度除法时,模拟日常除法的步骤。但计算机不可能做“试商”,这时,我们可以采用减法来模拟。
试商过程
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("-");
}
//处理乘数1
int len = strlen(s1);
a[0] = len;
for (int i=0; i<len; i++) {
a[len-i]=s1[i]-'0';
}
//处理乘数2
len = 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;
}
}
//控制最高位的0
while (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");
}
输出格式需要根据实际题目要求进行修改。
高精度除法:
#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] = {};//存储和B
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;
}
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("-");
}
//处理乘数1
int len = strlen(s1);
a[0] = len;
for (int i=0; i<len; i++) {
a[len-i]=s1[i]-'0';
}
//处理乘数2
len = 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;
}
}
//控制最高位的0
while (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;
}
我们高精度算法的最基本篇“加减乘除”已经完结,后期给大家讲高精度根号等等……