轉載: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;
}
int multi2(int a[],int b[]) //a=a*b
{
}
相關文章
- C++常用排序演算法 (轉)C++排序演算法
- [轉載]DSA演算法演算法
- [轉載]RSA演算法演算法
- [轉載]ElGamal演算法GAM演算法
- 【轉】c++ http下載檔案C++HTTP
- The main difference between Java & C++(轉載)AIJavaC++
- 轉載——C++記憶體管理C++記憶體
- C++讀二進位制檔案 及 C++設定double精度C++
- C++虛擬函式解析(轉載)C++函式
- (轉載)C++ ofstream和ifstream詳細用法C++
- 高精度加法(可以為負數)【C++版和java版】C++Java
- 零基預演算法(轉載)演算法
- MySQL 字串轉double轉換棧幀(可能丟失精度)MySql字串
- Dubbo之高階特性
- Java排序演算法速度比較(轉載)Java排序演算法
- 【轉載】C++ ,C#資料型別對照C++C#資料型別
- C++中extern “C”含義深層探索 (轉載)C++
- 雪花演算法ID在前端丟失精度解決方案演算法前端
- React手稿之高階元件React元件
- Stream之高階函式函式
- XenApp之高可用篇APP
- 【演算法】轉載:Iterative vs. Recursive Approaches演算法APP
- 轉載:記錄python幾個演算法:Python演算法
- C++演算法——BFSC++演算法
- 【譯】將字元轉換為雙精度浮點型字元
- 從‘void*’到‘int’的轉換損失精度
- 試題 演算法提高 小寫轉換為大寫 C++演算法C++
- [轉載] 陳皓:一些重要的演算法演算法
- C++ NFS掛載C++NFS
- React教程之高階元件React元件
- javascript黑科技之高效填充JavaScript
- mysql之高效能索引MySql索引
- webpack4之高階篇Web
- React 進階之高階元件React元件
- 演算法導論學習之補漏:高精度冪運算演算法
- 駭客攻擊技術之高階SQL隱碼攻擊技術(轉)SQL
- c++ 遞推演算法C++演算法
- C++泛型演算法C++泛型演算法