第一篇这样的开头 会不会 压迫我更加努力!就这样纪念 我的第一篇 报告吧!
前言 是我从网上 看到 对 高精度 觉得 还不错的 描述
前言:由于计算机运算是有模运算,数据范围的表示有一定限制,如整型int(C++中int 与long相同)表达范围是(-2^31~2^31-1),unsigned long(无符号整数)是(0~2^32-1),都约为几十亿.如果采用实数型,则能保存最大的double只能提供15~16位的有效数字,即只能精确表达数百万亿的数.因此,在计算位数超过十几位的数时,不能采用现有类型,只能自己编程计算.
高精度计算通用方法:高精度计算时一般用一个数组来存储一个数,数组的一个元素对应于数的一位(当然,在以后的学习中为了加快计算速度,也可用数组的一个元素表示数的多位数字,暂时不讲),表示时,由于数计算时可能要进位,因此为了方便,将数由低位到高位依次存在数组下标对应由低到高位置上,另外,我们申请数组大小时,一般考虑了最大的情况,在很多情况下,表示有富余,即高位有很多0,可能造成无效的运算和判断,因此,我们一般将数组的第0个下标对应位置来存储该数的位数.如数:3485(三千四百八十五),表达在数组a[10]上情况是:
下标 0 1 2 3 4 5 6 7 8 9
内容 4 5 8 4 3 0 0 0 0 0
说明:位数 个位 十位 百位 千位
具体在计算加减乘除时方法就是小学时采用的列竖式方法.
注:高精度计算时一般用正数,对于负数,通过处理符号位的修正.
下面 就用代码和讲解 说明 大数的加减乘 :
大数 首先 我们一般会用 字符串数组 来 保存 它,原因前言就有~! 而且 进行运算时 每一位对应 应该是倒序的 原因 前言也有~!
using namespace std;
const int N=1000;
char str1[N],str2[N];//存大数 的字符串数组
int a[N],b[N];//具体进行模拟每一位运算的整型数组
int compare(int a[],int b[]);//大数比较大小的函数
void add(int a[],int b[]);//
void gminus(int a[],int b[]);
int main()
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>str1>>str2;
a[0]=strlen(str1);
b[0]=strlen(str2);
for(int i=1;i<=a[0];i++)
a[i]=str1[a[0]-i]-'0';
for(int i=1;i<=b[0];i++)
b[i]=str2[b[0]-i]-'0';//以上是将存在字符串里的大数逆序读入整型数组
}
//比较两个大数谁大,想法代码都很简单!
int compare(int a[],int b[])
{
int i;
if(a[0]>b[0])
cout<<"前一个数更大"<<endl;
if(a[0]<b[0])
cout<<"后一个数更大"<<endl;
for(i=a[0];i>0;i--)
{
if(a[i]>b[i])
cout<<"前一个数更大"<<endl;
if(a[i]<b[i])
cout<<"后一个数更大"<<endl;
}
cout<<"两个数一样大"<<endl;//两数相等
}
//模拟两个大数的加法过程,也很简单
void add(int a[],int b[])
{
int len_max;
len_max=a[0]>b[0]?a[0]:b[0];//判断哪个大数长一些,加到那一步
for(int i=1;i<=len_max;i++)
{
a[i+1]+=(a[i]+b[i])/10;
a[i]=(a[i]+b[i])%10;
}
if(a[len_max+1]>0) //如果大于0,就进一位
a[0]=len_max+1;
else
a[0]=len_max;
for(int i=a[0];i>0;i--)
printf("%d",a[i]);
}
//模拟减法也很容易可以想到,如果是负数,输出的时候加个负号-.
void gminus(int a[],int b[])//大数减法
{
int flag2=compare(a,b);
printf("%d\n",flag2);
if(flag2==0)
{
memset(a,0,sizeof(a));
a[0]=1;
for(int i=a[0];i>0;i--)
printf("%d",a[i]);
}
if(flag2==1)//a比b大 正常减 a=a-b;
{
for(int i=1;i<=a[0];i++)
{
if(a[i]<b[i])
{
a[i+1]--;
a[i]+=10;
}
a[i]=a[i]-b[i];
}
if(a[a[0]]==0)
a[0]--;
for(int i=a[0];i>0;i--)
printf("%d",a[i]);
}
if(flag2==-1)//b比a大 a=-(b-a)
{
for(int i=1;i<=b[0];i++)
{
if(b[i]<a[i])
{
b[i+1]--;
b[i]+=10;
}
a[i]=b[i]-a[i];
}
a[0]=b[0];
if(a[a[0]]==0)
a[0]--;
printf("-");
for(int i=a[0];i>0;i--)
printf("%d",a[i]);
}
}
//大数乘以小数
int multi1(int a[],long key) //a=a*key,key是单精度数
{int i,k;
if (key==0){memset(a,0,sizeof(a));a[0]=1;return 0;} //单独处理key=0
for(i=1;i<=a[0];i++)
a[i]=a[i]*key;//先每位乘起来
for(i=1;i<=a[0];i++)
{a[i+1]+=a[i]/10;a[i]%=10;} //进位
//注意上一语句退出时i=a[0]+1
while(a[i]>0)
{a[i+1]=a[i]/10;a[i]=a[i]%10;i++;a[0]++];} //继续处理超过原a[0]位数的进位,修正a的位数
return 0;
}
直接上全部代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000;
char str1[N],str2[N];
int a[N],b[N],c[N];
int main()
{
cin>>str1;
cin>>str2;
memset(a,0,sizeof(a));
memset(a,0,sizeof(b));
int len_str1=strlen(str1);
int len_str2=strlen(str2);
for(int i=0;i<len_str1;i++)
a[i]=str1[len_str1-i-1]-'0';
for(int i=0;i<len_str2;i++)
b[i]=str2[len_str2-i-1]-'0';
for(int i=0;i<len_str1;i++)//核心代码 模拟竖式 乘法 过程 记住这里下标必须从0开始 不能是1
{
for(int j=0;j<len_str2;j++)
{
c[i+j]+=a[i]*b[j];
c[i+j+1]+=c[i+j]/10;
c[i+j]%=10;
}
}
int len=len_str1+len_str2;
while(!c[len])len--;
for(int i=len;i>=0;i--)
cout<<c[i];
cout<<endl;
}
终于 打完 所有我想记录下的 代码和话语~!算了解 这两天的心愿 ,好吧 我承认 我就算写完 这一篇很水的报告,我的a题能力不会有任何的提高,大神们也根本不懈不会来这里看这种没有营养的报告,不管怎样 我终于迈出了写博客的第一步~!(妈蛋 明天 还有c++上机实验 我书都没看~!)