程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 轉載:C++之高精度算法,轉載高精度算法

轉載:C++之高精度算法,轉載高精度算法

編輯:C++入門知識

轉載:C++之高精度算法,轉載高精度算法


C++之高精度算法

注意:本文轉載自http://blog.sina.com.cn/s/blog_4fdb102b010087ng.html,十分感謝原作者:忍者    前言:由於計算機運算是有模運算,數據范圍的表示有一定限制,如整型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
說明:位數   個位  十位  百位 千位
具體在計算加減乘除時方法就是小學時采用的列豎式方法.
注:高精度計算時一般用正數,對於負數,通過處理符號位的修正.
一.高精度數的存儲
1.如對數采用的字符串輸入
#include <iostream>
#include <cstring>
using namespace std;
const int N=100;//最多100位
int main()
{
int a[N+1],i;
string s1;
cin>>s1;//數s1
memset(a,0,sizeof(a)); //數組清0
a[0]=s1.length(); //位數
for(i=1;i<=a[0];i++) a[i]=s1[a[0]-i]-'0';//將字符轉為數字並倒序存儲.
return 0;
}
2.直接讀入
#include <iostream>
using namespace std;
const int N=100;//最多100位
int main()
{
int a[N+1],i,s,key;
cin>>key;//數key
memset(a,0,sizeof(a)); //數組清0
i=0;//第0位
while(key)  //當key大於0
{
  a[++i]=key%10;//取第i位的數
  key=key/10;
}
a[0]=i; //共i位數
return 0;
}
3.直接初始化(用a[]存儲)
初始化為0: memset(a,0,sizeof(a));
初始化為1: memset(a,0,sizeof(a));a[0]=1;a[1]=1;

以下程序都只寫函數,不寫完整程序,所有高精度數存儲都滿足上述約定。
二.高精度數比較
int compare(int a[],int b[])   //比較a和b的大小關系,若a>b則為1,a<b則為-1,a=b則為0
{int i;
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;//各位都相等則兩數相等。
}
三、高精度加法
int plus(int a[],int b[]) //計算a=a+b
{int i,k;
k=a[0]>b[0]?a[0]:b[0]; //k是a和b中位數最大的一個的位數
for(i=1;i<=k;i++)
    {a[i+1]+=(a[i]+b[i])/10;  //若有進位,則先進位
    a[i]=(a[i]+b[i])%10;}  //計算當前位數字,注意:這條語句與上一條不能交換。
if(a[k+1]>0) a[0]=k+1;  //修正新的a的位數(a+b最多只能的一個進位)
               else a[0]=k;
return 0;
}
四、高精度減法
int gminus(int a[],int b[]);//計算a=a-b,返加符號位0:正數 1:負數
{ int flag,i
  flag=compare(a,b); //調用比較函數判斷大小
if (falg==0)//相等
  {memset(a,0,sizeof(a));return 0;}  //若a=b,則a=0,也可在return前加一句a[0]=1,表示是 1位數0
if(flag==1) //大於  
  {  for(i=1;i<=a[0];i++)
      {  if(a[i]<b[i]){ a[i+1]--;a[i]+=10;} //若不夠減則向上借一位
        a[i]=a[i]-b[i];}
     while(a[a[0]]==0) a[0]--; //修正a的位數
    return 0;}
if (flag==-1)//小於  則用a=b-a,返回-1
    { for(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];
     while(a[a[0]]==0) a[0]--; //修正a的位數
    return -1;}
}
五、高精度乘法1(高精度乘單精度數,單精度數是指通常的整型數)
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;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved