C语言实现高精度算法
前言.为什么需要高精度算法:在我们写代码时, 有时会处理一些较大数的运算,这些数甚至超过了unsigned long long的范围:
(0~2^64-1=18446744073709551615)。
此时需要用字符串数组来存储数字,运算时需要特殊的算法进行运算,称为高精度算法。 高精度算法本质上是模拟数字的运算。
一级目录 高精度加法
在写高精度加法之前,先让我们回顾一下小学(或者是幼儿园)就学过的加法公式:
演示 | 1985 |
---|---|
+ | 2566 |
每位数分别相加 | 3 14 14 11 |
大于十则进一位 | 4 4 5 1 |
其结果就是:1985+2566=4451
高精度加法正是模拟了这个运算过程,代码实现如下:
#include<stdio.h>
#include<string.h>
#define max 1000
int main(void)
{
char str[max];
int arr1[max]={0},arr2[max]={0};//初始化数组
int len1,len2,len,i;
scanf("%s",str);
len1=strlen(str);
for(i=0;i<len1;i++)
arr1[i]=str[len1-1-i]-'0';//这里将数字倒置输入数组方便计算
scanf("%s",str);
len2=strlen(str);
for(i=0;i<len2;i++)
arr2[i]=str[len2-1-i]-'0';
len=(len1>len2)?len1:len2;//比较两个数的位数,取最大位数
for(i=0;i<len;i++)
{
arr1[i]+=arr2[i];//每位分别相加
arr1[i+1]+=arr1[i]/10;//如果这位大于10,则进一
arr1[i]%=10;//留下个位数
}
len++;
if((arr1[len]==0))//判断最高位是否为零
len--;
for(i=len;i>=0;i--)
printf("%d",arr1[i]);
return 0;
}
二级目录 高精度乘法
高精度乘法的原理也是对每位分别进行计算,思路基本与高精度加法相同
a、通过两个字符串输入两个整数;
b、引人两个数组,将两个整数通过一定的运算,分别将每一位的数字储存进数组中;
c、进行每一位的运算;
d、处理进位;
e、输出结果;
代码实现如下:
#include<stdio.h>
#include<string.h>
#define max 1000
int main(void)
{
char str[max];
int arr1[max]={0},arr2[max]={0},arr[2*max]={0};//新引入一个数组用来存放两数相乘的结果
int len1,len2,len,i,j;
scanf("%s",str);
len1=strlen(str);
for(i=0;i<len1;i++)
arr1[i]=str[len1-1-i]-'0';
scanf("%s",str);
len2=strlen(str);
for(i=0;i<len2;i++)
arr2[i]=str[len2-1-i]-'0';
for(i=0;i<len1;i++)
{
for(j=0;j<len2;j++)
arr[i+j]+=arr1[i]*arr2[j];
if(arr[i]>=10)
{
arr[i+1]+=arr[i]/10;
arr[i]%=10;
}
}
len=len1+len2;//两个自然数的积的位数,等于这两个数的位数的和,或者比这个和少1。
if(arr[len-1]==0)
len--;
for(i=len-1;i>=0;i--)
printf("%d",arr[i]);
return 0;
}
三级目录 高精度加法与乘法的综合应用—求100以内数的阶乘和
题目链接:100以内阶乘和
这道题乍看很简单,似乎只要用一个循环就能解决,但如果真这样写了只能得50分,原因正如我们一开始所讲,数据过大超出了数据类型所能存储的范围,因此只能用高精度模拟运算解决。
#include<stdio.h>
#include<string.h>
#define max 1000
int main(void)
{
int n,i,j,k,book;
scanf("%d",&n);
int arr1[max]={1},arr2[max]={1};//想想看这里为什么两个都要初始化为1
for(i=2;i<=n;i++)//用i表示阶乘和
{
for(j=0;j<=101;j++)
arr2[j]*=i;//高精度乘法求阶乘
for(j=0;j<=101;j++)
{
if(arr2[j]>=10)
{
arr2[j+1]+=arr2[j]/10;
arr2[j]%=10;
}
}
for(k=0;k<=101;k++)//高精度加法将阶乘相加
{
arr1[k]+=arr2[k];
if(arr1[k]>=10)
{
arr1[k+1]+=arr1[k]/10;
arr1[k]%=10;
}
}
}
for(i=100;i>=0;i--)//去掉最高位的零
{
if(arr1[i]!=0)
{
book=i;
break;
}
}
for(i=book;i>=0;i--)//输出
printf("%d",arr1[i]);
return 0;
}
高精度减法与除法的实现相对于加法和乘法来说复杂一些,我们留到下篇文章再讲。