首页 > 编程语言 >高精度算法

高精度算法

时间:2023-05-21 16:32:41浏览次数:39  
标签:10 高精度 int -- 算法 maxn include

先来看一下每个数据类型可表示的数据范围

高精度算法_高精度

当我们要表示的数很长时,无法用数据类型表示,可以用数组存储

单精度:用一个内置类型存储的整数

高精度:不能内置类型存储的大整数,通常用数组存储每一个数位

建议使用小端存储(个位放在最前面)(原因:大端存储虽然看似更直观,但是当处理进位时就会遇到问题:必须要将所有元素移位,为新位腾出空间!方便模拟竖式运算!)


高精度加法

按照竖式计算方法,①从低位到高位,②对于较长数的每一位i,和的第i位为两加数第i位与当前进位三者之和,③若和大于10,则下一进位为1,当前位和减10,④结束后,若进位非0,则结果增加一位,值为进位(此处必为1)

// 从低到高位计算
for (int i = 0; i < len; i++) {
// 和的第i位为两加数第i位与当前进位三者之和
c[i] += a[i] + b[i];
// 若和大于10,则下一进位为1
c[i + 1] = c[i] / 10;
// 当前位和减10
c[i] %= 10;
}
// 结束后,若进位非0,则结果增加一位,值为进位(此处必为1)
if (c[len + 1])len++;
完整程序:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 520
using namespace std;
int a[maxn], b[maxn], c[maxn]
int main()
{
    string A,B;
    cin>>A>>B; //输入加数与被加数
    int len=max(A.length(),B.length());//和的位数与最大值的位数有关
    for (int i=A.length()-1,j=1; i>=0;i--,j++) 
    	a[j]=A[i]-'0';     //加数放入a数组
   for (int i=B.length()-1,j=1; i>=0;i--,j++) 
    	b[j]=B[i]-'0';
    for (int i=1; i<=len;i++){
    	c[i]+=a[i]+b[i];
        c[i+1]=c[i]/10;
        c[i]%=10;
    }
    if(c[len+1])len++;
    for(int i=len;i>=1;i--)cout<<c[i];
    return 0;

使用数组0~(n-1)和使用数组1~n在进行高精度运算时,分别有什么好处?

高精度乘法

算法分析

类似加法,可以用竖式求乘法。

分析c数组下标的变化规律,可以写出如下关系式:ci = c’i +c”i +…由此可见,c i跟a[i]*b[j]乘积有关,跟上次的进位有关,还跟原c i的值有关,可以把所有贡献算出来,最后一口气处理进位问题,有

c[i+j-1]= a[i]*b[j]+ x + c[i+j-1]; 

x=c[i+j-1]/10 ; 

c[i+j-1]%=10;

高精度算法_高精度_02

完整程序如下:
#include<iostream>
#include<cstring>
#define maxn 5010
using namespace std;
int a[maxn],b[maxn],c[maxn];
int main()
{
    int i,j,x,lena,lenb,lenc;
    string A,B;
    cin>>A>>B;
    lena=A.length();lenb=B.length();
    for (i=lena-1;i>=0;i--) a[lena-i]=A[i]-48;
    for (i=lenb-1;i>=0;i--) b[lenb-i]=B[i]-48;
  	for (i=1;i<=lena;i++)        
	    for (j=1;j<=lenb;j++)           
			c[i+j-1]+=a[i]*b[j];
	lenc=lena+lenb;
	for(i=1;i<=lenc;i++){
		c[i+1]+=c[i]/10;
		c[i]%=10;
	}
	for(;!c[lenc];)lenc--;
	for (i=max(lenc,1);i>=1;i--)
		cout<<c[i]; 
	return 0;
}

补充:高精度减法

算法分析

类似加法,可以用竖式求减法。在做减法运算时,需要注意的是:被减数必须比减数大,同时需要处理借位。

减法进位
if (a[i]<b[i]) { 
    --a[i+1]; 
    a[i]+=10; 
}

c[i]=a[i]-b[i];
完整程序如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 520
using namespace std;
int a[maxn], b[maxn], c[maxn];
int main()
{
    int i,j,lena,lenb,lenc;
    char A[maxn],B[maxn],C[maxn];
    gets(A);
    gets(B);
    if (strlen(A)<strlen(B)||strlen(A)==strlen(B)&&strcmp(A,B)<0)//strcmp()为字符串比较函数,当n1==n2, 返回0,A>B时,返回正整数;A<B时,返回负整数
    {//处理被减数和减数,交换被减数和减数
    	strcpy(C,A);
    	strcpy(A,B);
    	strcpy(B,C);
    	cout<<"-";
    
	}
	lena=strlen(A),lenb=strlen(B);
	for(i=lena-1,j=1;i>=0;i--,j++)
    	a[j]=A[i]-'0';     //加数放入a数组
    for(i=lenb-1,j=1;i>=0;i--,j++){
    	b[j]=B[i]-'0';
	}
	i=1;
    while (i<=lena||i<=lenb)
    {
        if (a[i]<b[i])
        {
            a[i]+=10;//不够减,那么向高位借1当10
            a[i+1]--;
        }
        c[i]=a[i]-b[i];//对应位相减
        i++;
    }
    lenc=i;
    while ((c[lenc]==0)&&(lenc>1)) lenc--;//最高位的0不输出    
    for (i=lenc;i>=1;i--) cout<<c[i];//输出结果
    return 0;
}

高精度除法

1. 高精度数除以单精度数
算法分析

做除法时,每一次上商的值都在0~9,每次求得的余数连接以后的若干位得到新的被除数,继续做除法。

因此,在做高精度除法时,要涉及到乘法运算和减法运算,还有移位处理。

当然,为了程序简洁,可以避免高精度除法,用0~9次循环减法取代得到商的值。这里,我们讨论一下高精度数除以单精度数的结果,采取的方法是按位相除法。

完整程序如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
	char a1[100],c1[100];
  	int a[100],c[100],lena,i,x=0,lenc,b;
  	memset(a,0,sizeof(a));
  	memset(c,0,sizeof(c));
  	gets(a1);
  	cin>>b;
  	lena=strlen(a1);
  	for (i=0;i<=lena-1;i++)
  		a[i+1]=a1[i]-48;
     		for (i=1;i<=lena;i++)                               //按位相除
		{
			c[i]=(x*10+a[i])/b;
	    		x=(x*10+a[i])%b;
		}
  		lenc=1;
    		while (c[lenc]==0&&lenc<lena) 
  			lenc++;                                      //删除前导0
    		for (i=lenc;i<=lena;i++) 
    		cout<<c[i];
    		cout<<endl;
    		return 0;
}

实质上,在做两个高精度数运算时候,存储高精度数的数组元素可以不仅仅只保留一个数字,而采取保留多位数(例如一个整型或长整型数据等),这样,在做运算(特别是乘法运算)时,可以减少很多操作次数。

例如图5就是采用4位保存的除法运算,其他运算也类似。具体程序可以修改上述例题予以解决,程序请读者完成。


2.高精除以高精
算法分析
高精除以低精是对被除数的每一位(这里的“一位”包含前面的余数,以下都是如此)都除以除数,而高精除以高精则是用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数(由于每一位的数字小于10,所以对于每一位最多进行10次计算)
完整程序如下:
#include<iostream>
#include<cstring>
using namespace std;
int a[101],b[101],c[101],d,i;   
void init(int a[]) 
{    string s; 
	cin>>s;                        //读入字符串s 
	a[0]=s.length();           //用a[0]计算字符串 s的位数 
	for(i=1;i<=a[0];i++)
	a[i]=s[a[0]-i]-'0';          //将数串s转换为数组a,并倒序存储. 
}
void print(int a[])              //打印输出
{
	if (a[0]==0){cout<<0<<endl;return;}
	for(int i=a[0];i>0;i--) cout<<a[i];
	cout<<endl;
	return ;
}
int compare (int a[],int b[])  
			//比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0 
{
	if(a[0]>b[0]) return 1;                    //a的位数大于b则a比b大 
	if(a[0]<b[0]) return -1;                   //a的位数小于b则a比b小 
	for(i=a[0];i>0;i--)                           //从高位到低位比较 
	{
		if (a[i]>b[i]) return 1; 
		if (a[i]<b[i]) return -1;
	} 
	return 0;                                        //各位都相等则两数相等。 
} 

void numcpy(int p[],int q[],int det)      //复制p数组到q数组从det开始的地方
{
	for (int i=1;i<=p[0];i++) q[i+det-1]=p[i];
	q[0]=p[0]+det-1;
}

void jian(int a[],int b[])               //计算a=a-b
{ 
	int flag,i; 
	flag=compare(a,b);              //调用比较函数判断大小 
	if (flag==0) {a[0]=0;return;}   //相等 
	if(flag==1)                             //大于   
	{
		for(i=1;i<=a[0];i++) 
		{
			if(a[i]<b[i]){ a[i+1]--;a[i]+=10;}         //若不够减则向上借一位 
			a[i]-=b[i];
		} 
		while(a[0]>0&&a[a[0]]==0) a[0]--;               //修正a的位数 
		return;
	} 
} 

void chugao(int a[],int b[],int c[])
{
	int tmp[101]; 
	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]++;jian(a,tmp);}  //用减法来模拟
	}
	while(c[0]>0&&c[c[0]]==0)c[0]--;
	return ;
}

int main()
{
  	memset(a,0,sizeof(a));
  	memset(b,0,sizeof(b));
  	memset(c,0,sizeof(c));
  	init(a);init(b);
  	chugao(a,b,c);
  	print(c);
  	print(a);
  	return 0;
}


标签:10,高精度,int,--,算法,maxn,include
From: https://blog.51cto.com/u_15901728/6319684

相关文章

  • #球钟算法题解以及代码完成
    球钟问题描述:球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,5分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。       工作原理:每过一分钟,球钟就会从球队列的队首......
  • 【计算机视觉1】----- 图像增强算法(对比度增强、直方图均衡化)
    直方图均衡化直方图修正(HistogramEqualization)是一种常见的图像增强技术,它通过重新分布图像像素的灰度值来增强图像的对比度和亮度。直方图修正的基本思想是将图像的灰度值范围映射到一个更广泛的范围,从而使图像的灰度级分布更加均匀。注意,在运行代码之前,请确保已安装并配置了Ope......
  • PACS图像处理高级精准算法
    PACS对图像可进行各种算法的图像处理,包括平滑、锐化、降噪、边缘提取、灰度均衡、图像相减、图像平均、图像融合、组织均衡、自定义卷积核、自适应均衡、对比度均衡、腰椎均衡、数据分析;高级操作里面都是一些医学图像处理中常用的算法,如:平滑:轻度平滑、适度平滑、高度平滑;锐化:轻......
  • Delaunay三角剖分——BW算法
    Delaunay三角剖分定义在数学和计算几何中,对于给定的平面中的离散点集P ,其Delaunay三角剖分DT()满足:空圆性:DT(P)是 唯一 的(任意四点不能共圆),在DT(P)中,任意 三角形的外接圆范围内不会有其它点存在。最大化最小角:在点集P 可能形成的三角剖分中,DT(P)所形成的三角形......
  • 算法学习记录:P1387 最大正方形
    题目链接https://www.luogu.com.cn/problem/P1387解题思路固定左上角的点,枚举所有边长即可。随记:昨天脑子特乱,下标,越界什么的都没想好就开始写了,因为思路不清晰时写的,写出来的代码,调bug都不知道怎么调,对自己写的东西不够理解,在哪打印输出也不知道(循环一多自己就乱了),一个bug......
  • 算法的时间复杂度
    算法的时间复杂度是指在计算机执行该算法时所需要的时间和输入规模之间的关系。常见的时间复杂度有:1.O(1):常数时间复杂度,表示无论输入规模大小是多少,算法都需要相同的时间完成。例如读取数组中某个元素。2.O(logn):对数时间复杂度,表示算法的运行时间随输入规模增长而增长,但增......
  • 拓展欧几里得算法
    1.拓展欧的用处:求解方程\(ax+by==m\)的一组解2.拓展欧的一般性条件:对于方程\(ax+by=m\),当\(gcd(a,b)\)是m的整数倍时必定有解3.求解:设\(d=gcd(a,b)\),则特解为\(\begin{cases}x=x_0+\frac{d}{m}\quad\\y=y_0+\frac{d}{m}\quad\\\end{cases}......
  • 【代码随想录算法训练营第一天】704. 二分查找、27. 移除元素
    Day1-数组Leetcode704二分查找初解已经不记得二分查找了,遍历找O(n)其实也过了,只是借此复习一下二分,确实快很多。二分的前提条件题目里也都明示了:无重复,(从小到大)排序。我没有用到这个条件,自然时间复杂度高于最优解。看完解答我再看了一眼题目的标题,才知道是考BinarySearch嗯......
  • C# 版本 最少金币问题 动态规划 算法
    @[TOC](C#版本最少金币问题动态规划算法)<hrstyle="border:solid;width:100px;height:1px;"color=#000000size=1">题目这是一道经典算法题,题目如下:题目:有面值为2元,5元,7元面值的硬币,买一本27元的书,用最少的硬币组合刚好付清,问题1:需要几枚硬币。问题2:这几枚硬币都是什么?<......
  • 算法学习笔记合集
    字符串哈希:哈希学习笔记KMP:KMP学习笔记图论分层图最短路:分层图最短路LCA:P3379最近公共祖先模板数据结构线段树:线段树学习笔记ST表:P3865ST表树状数组:P3374树状数组1DP树上背包:P2014选课(树上背包)杂项搜索:搜索学习笔记离散化:离散化学习笔记......