A.pro讀演算法の2:高精度演算法
1.1 描述
高精度演算法,屬於處理大數字的數學計算方法。在一般的科學計算中,會經常算到小數點後幾百位或者更多,當然也可能是幾千億幾百億的大數字。一般這類數字我們統稱為高精度數,高精度演算法是用計算機對於超大資料的一種模擬加,減,乘,除,乘方,階乘,開方等運算。對於非常龐大的數字無法在計算機中正常儲存,於是,將這個數字拆開,拆成一位一位的,或者是四位四位的儲存到一個數組中, 用一個數組去表示一個數字,這樣這個數字就被稱為是高精度數。高精度演算法就是能處理高精度數各種運算的演算法,但又因其特殊性,故從普通數的演算法中分離,自成一家。
對於這類問題,不要指望int double這些東西了,基本資料型別不可能存的下。我們可以把這兩個數當成字串輸入到陣列中,然後模擬手動的豎式運算(不會的話,回去上小學)得出結果。
說白了,高精度計算就是解決long long也解決不了的問題。
1.2 分析與處理資料
1.2.1 當要處理的資料很長時,我們可以採用字串的方式輸入,這樣可以輸入很長的數,利用字串函式和操作運算,將每一位數取出,存入一個數組裡。
//1.2.1 資料的接收和儲存方法 void input() { string s; cin>>s;//讀入字串 a[0]=s.length();//取s字串的長度,並存入a[0]中 for(i=1;i<=a[0];i++) { a[i]=s[a[0]-i]-'0';//將字串s轉化為數字存入a陣列中,並倒敘儲存 //為什麼要倒敘?為了給進位留足空間 //高精度的儲存是把每一位單獨儲存,且是倒序儲存,陣列a[1]是這個數的個位,a[2]是這個數的十位,以此類推 } }
1.2.2 接收時使用字串,所以它的位數等於字串的長度。
1.2.3 當兩個運算元長度不一樣時,需要進行補零。
//1.2.3 補零問題 void NumFill() { string s1,s2; int len1,len2,i; cin>>s1>>s2;//讀入字串 len1=s1.length();//求字串1長度 len2=s2.length();//求字串2長度 if(len1<len2)//如果字串1長度小於字串2長度 {//對字串1補零 for(i=1;i<=len2-len1;i++)//len2-len1就是需要補零的長度 { s1='0'+s1; } } else//否則字串1長度大於字串2長度 {//對字串2補零 for(i=1;i<=len1-len2;i++)//len1-len2就是需要補零的長度 { s2='0'+s2; } } }
1.2.4 進位與借位
//1.2.4 進位處理
void plus()//加法進位
{
c[i]=a[i]+b[i];//虛擬碼,c[i]來儲存高精度數,a[i]和b[i]是被分離的2個加數。
if(c[i]>=10)//如果a[i]+b[i]大於0了,很顯然,要進位。不知道的給我重讀1年級數學
{
c[i]=c[i]%10;//把得到的結果分離出來
++c[i+1];//那麼後一位進一
}
}
void minus()//減法借位
{
if(a[i]<b[i])//先判斷被減數是否小於減數
{
--a[i+1];//後一位借位,所以減1
a[i]+=10;//那麼當前加10
}
c[i]=a[i]-b[i];//這個時候算差
}
void multiplication()//乘法進位
{
c[i+j-1] = a[i]*b[i]+x+c[i+j-1];//x表示的是進位數
//我們再宣告一個數組c來儲存答案。大家通過一個簡單的乘法運算進行模擬就可以看出。
//結果 = 當前乘積a[i]*b[i] + 進位數x + 原數
x=c[i+j-1]/10;//需要的進位數
c[i+j-1]%=10;//取下一位數
//這裡應該有for迴圈的
}
1.3 高精度計算演算法和思想
1.3.1 高精度加法
在讀小學時,我們做加法都採用豎式方法,利用豎式,我們可以寫出兩個整數相加的高精度演算法。
那麼,要想求出高精度資料,就需要一定的步驟演算法。
1.字元轉數字,且低位對齊;
2.a、b兩個陣列的長度,取較長的。相加時,考慮進位;
3.考慮得數的長度和0位;
4.逆序輸出。
Ps:其實低位對齊和逆序,只是方便計算和順應演算法思想罷了,不必要去思考為什麼要這樣做。
//1.3.1 高精度加法
#include <cstdio>
#include <iostream>
#include <cstring>
#define r(i,a,b) for(i=a;i<=b;i++)//為了省事而已
using namespace std;
int main()
{
char a1[101]={},b1[101]={};
int a[101]={},b[101]={},c[101]={},lena,lenb,lenc,i,x;
gets(a1);
gets(b1);
lena=strlen(a1);//取長度
lenb=strlen(b1);//取長度
r(i,0,lena-1)//從0到陣列長度-1正好把資料讀完
{
a[lena-i]=a1[i]-48;//字元轉數字
}
r(i,0,lenb-1)//從0到陣列長度-1正好把資料讀完
{
b[lenb-i]=b1[i]-48;//字元轉數字
}
lenc=1;//用來處理陣列長度
x=0;//用來計算進位
while(lenc<=lena || lenc<=lenb)//開始計算,演算法核心
{
c[lenc]=a[lenc]+b[lenc]+x;//得到的結果,應該是a[]+b[],當然還要加上進位
x=c[lenc]/10;//其實不用寫if,如果此答案低於10得到的進位還是0,超過10就是1
c[lenc]%=10;//此答案取後一位,如果只有1位數,還是本身
lenc++;//繼續判斷下一位
}
if(x==0)//如果最後一位可以進位
lenc--;
for(i=lenc;i>=1;i--)//逆序輸出
cout<<c[i];
cout<<endl;
return 0;
}
1.3.2 高精度減法
類似加法,可以用豎式求減法。在做減法運算時,需要注意的是:被減數必須比減數大,同時需要處理錯位以及前導0。
步驟和演算法設計
1.字元轉數字,且低位對齊;
2.取a,b2個數組長度更長的那個,注意可能會有負號;
3.計算時可能會有進位;
4.高位是否存在;
5.逆序輸出。
//1.3.2 高精度減法
#include <cstdio>
#include <cstring>
#include <iostream>
#define r(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int a[257],b[257],c[257],lena,lenb,lenc,i;
char n[257],n1[257],n2[257];
int main()
{
cin>>n1>>n2;
if(strlen(n1)<strlen(n2) || (strlen(n1)==strlen(n2) && strcmp(n1,n2)<0))//如果被減數小於減數,值為負,兩者交換
{
strcpy(n,n1);
strcpy(n1,n2);
strcpy(n2,n);//字元交換
cout<<'-';//先輸出負號
}
lena=strlen(n1);
lenb=strlen(n2);
r(i,0,lena-1)//被減數存入陣列a
{
a[lena-i]=int(n1[i]-'0');//字元轉數字
}
r(i,0,lenb-1)//減數存入陣列a
{
b[lenb-i]=int(n2[i]-'0');//字元轉數字
}
i=1;//控制當前陣列下標
while(i<=lena || i<=lenb)//開始計算,核心演算法
{
if(a[i]<b[i])//如果被減數比減數小,要借位
{
a[i]=a[i]+10;
a[i+1]--;
}
c[i]=a[i]-b[i];//因為判斷是否借位了,直接減即可
i++;
}
lenc=i;
while((c[lenc]==0)&&(lenc>1))//判斷高位是否為0,最高位0不輸出
lenc--;
for(i=lenc;i>=1;i--)//逆序輸出
cout<<c[i];
cout<<endl;
return 0;
}
1.3.3 高精度乘法
類似加法,用豎式求乘法。在做乘法運算時,同樣有進位,同時對每一位進行乘法運算時,必須進行錯位相加。
//1.3.3 高精度乘法
#include <cstdio>
#include <cstring>
#include <iostream>
#define r(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int a[257],b[257],c[257],lena,lenb,lenc,i,j,x;
char a1[257],b1[257];
int main()
{
cin>>a1>>b1;
lena=strlen(a1);
lenb=strlen(b1);
r(i,0,lena-1)
{
a[lena-i]=int(a1[i]-'0');
}
r(i,0,lenb-1)
{
b[lenb-i]=int(b1[i]-'0');
}
r(i,1,lena)
{
x=0;//存放進位
r(j,1,lenb)//對乘數的每一位都處理
{
c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//結果 = 當前乘積a[i]*b[i] + 進位數x + 原數
x=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[i+lenb]=x;//是否需要進位
}
lenc=lena+lenb;//根據乘法的原理計算計算最大長度
//99*99,最大長度是4
//11*10,最大長度是3
while(c[lenc]==0 && lenc>1)//刪除前導0
{
lenc--;
}
for(i=lenc;i>=1;i--)
cout<<c[i];
cout<<endl;
return 0;
}
1.3.4 高精度除法,高精除以低精
做除法時,每一次的商的值都在0~9,每次求得的餘數連線以後的若干位得到新的被除數,繼續做除法。因此在做高精度除法時,要涉及到乘法運算和減法運算以及移位處理。
為程式簡潔,可以避免高精度乘法,用0~9次迴圈減法取代得到商的值,對於高精度數除以低精度數,我們採用按位相除法。
//1.3.4 高精度除法,高精除以低精
#include <cstdio>
#include <cstring>
#include <iostream>
#define r(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int b,a[257],c[257],lena,lenc,i,j,x=0;//x是餘數
char a1[257],c1[257];
int main()
{
cin>>a1>>b;//注意,此時高精除以低精
lena=strlen(a1);
r(i,0,lena-1)
{
a[i+1]=a1[i]-'0';
}
r(i,1,lena)//模擬除法豎式,按位相除
{
c[i]=(x*10+a[i])/b;
x=(x*10+a[i])%b;
}
lenc=1;
while(c[lenc]==0&&lenc<lena)//刪除前導0
lenc++;
for(i=lenc;i<=lena;i++)
cout<<c[i];
cout<<endl;
return 0;
}
本來還有個1.3.5的,高精數除以高精數,A.pro智力有限還沒想好..
2.1 C++ 大整數類模版--<2018.08.19更新>
相關推薦
A.pro讀演算法の2:高精度演算法
1.1 描述 高精度演算法,屬於處理大數字的數學計算方法。在一般的科學計算中,會經常算到小數點後幾百位或者更多,當然也可能是幾千億幾百億的大數字。一般這類數字我們統稱為高精度數,高精度演算法是用計算機對於超大資料的一種模擬加,減,乘,除,乘方,階乘,開方等運算。對於非常龐大
無人駕駛入門2:高精度地圖
復雜 學習 地圖數據 規劃 進行 信息 智能手機 領導 思考 自從上次發布了《無人駕駛入門1:無人駕駛概覽》,就收到了不少的鼓勵和鞭策,包括前領導的肯定。那我們趕緊來學習第二課關於高精度地圖的課程吧。 第二課: 高精度地圖 課程簡介:了解高精度地圖的實現邏輯,這是 Apol
資料結構學習(一):高精度演算法
高精度演算法,屬於處理大數字的數學計算方法。在一般的科學計算中,會經常算到小數點後幾百位或者更多,當然也可能是幾千億幾百億的大數字。一般這類數字我們統稱為高精度數,高精度演算法是用計算機對於超大資料的一種模擬加,減,乘,除,乘方,階乘,開方等運算。對於非常龐大的數字無法在計算機中正常儲存
tensorflow基本演算法(2):最近鄰演算法nearest neighbor
參考維基百科: 在模式識別領域中,最近鄰居法(KNN演算法,又譯K-近鄰演算法)是一種用於分類和迴歸的非引數統計方法。在這兩種情況下,輸入包含特徵空間中的k個最接近的訓練樣本。 在k-NN分類中,輸出是一個分類族群。一個物件的分類是由其鄰居的“多數表決”確定的,k個最近鄰
A.pro讀演算法の11:最短路徑之Dijkstra演算法
此文是獻給OIer看的。講的東西比較基礎(其實我理解Dijkstra花了很長時間)。NOIP2018結束約有1個月了,但是我們仍要繼續前進,為NOIP2019做準備。本節學習Dijkstra的演算法思想和實現,以及優先佇列和堆優化。線段樹也可以做到優化,甚至可能還更快,但是我太弱了不會。。
A.pro讀演算法--報刊(持續更新)
第1期(2018.05.29):A.pro讀演算法の1:貪心演算法 第2期(2018.06.16):A.pro讀演算法の2:高精度演算法 第3期(2018.07.24):A.pro讀演算法の3:二分查詢及模板 第4期(2018.08.01):A.pro讀演算法の4:搜尋演算法 第
【高精度演算法】A/B 高精度除以低精度 保留小數
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> cha
【高精度演算法】A-B(答案可負)
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> cha
資訊學奧賽一本通演算法(C++版)基礎演算法:高精度計算 高精度加法(大位相加)
2018年資訊學奧賽NOIP資料下載 1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 char a1[100],b1[100]; 6 int a[100],b[100],c[100];/
Linux時間子系統之六:高精度定時器(HRTIMER)的原理和實現
3.4 size 屬於 running return repr 而是 復雜度 ctu 上一篇文章,我介紹了傳統的低分辨率定時器的實現原理。而隨著內核的不斷演進,大牛們已經對這種低分辨率定時器的精度不再滿足,而且,硬件也在不斷地發展,系統中的定時器硬件的精度也越來越高,這也給
模板:高精度求積
str memset cout ext lse == font esp ble http://lfyzit.com/problem/45 1 #include<iostream> 2 #include<string> 3 #include&l
模板:高精度
swa size can ++ memset line const iostream 高精度模板 先把自己以前打的高精度模板放上來吧,湊一篇的樣子(原題: 洛谷1932 )。。。 #include <iostream> #include <cstdio&g
NOIP複賽複習(四)讀寫外掛與高精度模板
讀入輸出掛 讀入輸出掛就是逐個字元地讀入資料,從而讓讀入更加快速。輸出掛的原理也是一樣的,都是通過將輸出數字變成輸出字元以加快速度。當然輸入輸出外掛一般用在大量輸入輸出的情況下,這樣價效比才高一些,否則得不償失。 void Rd(int &res){ &nbs
c++高精度演算法-大整數運算
#include<iostream> #include<vector> #include<cstring> using namespace std; struct BigInteger{ static const int BASE=100000000;
高精度演算法模板索引
1、四則運算 高精加高精 高精減高精 高精乘高精(FFT優化) 高精除高精 2、四則運算 高精加低精 高精減低精 高精乘低精 高精除低精 3、其他運算 高精取模高精 高精取模低精 高精比較
hdu 1042 高精乘低精 高精度演算法
Problem Description Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N! Input One N in one line, process to th
資訊學奧賽系列教程:高精度計算
為什麼要需要高精度計算? 每種計算機語言的基本資料型別,都有一定的範圍限制,在一些科學計算中,當需要運算的算數(加數、減數、乘數、除數)大於基本資料型別所能表示的範圍時,需要通過演算法來實現這些運算,比如200位的兩個數相乘 高精度計算需要解決的問題: 1、資料的
[C++]高精度演算法
目錄 高精度加法 高精度減法 高精度乘法 高精度除法 高精度階乘 高精度加法 用程式來模擬豎式加法即可,注意在輸出的時候除去多餘的前導零
每週一演算法(2):費式數列
即斐波那契數列,小學可能就知道它的規律了,即該數是前兩個之和。 例如:1、1、2、3、5、8、13、21、34、55、89…… 按照它的規律: 即:Fn = Fn -1 + Fn-2 n>1 &
資訊學奧賽系列教程:高精度除法
我們平時做除法時,採用立豎式的方法計算: 被除數從高位開始,和被除數對齊,諸位“試商”,“試商”後被除數減去“試商”的數的乘積,如下圖所示: 採用計算機做高精度除法時,模擬日常除法的步驟。但計算機不可能做“試商”,這時,我們可以採用減法來模擬 "試商"的過程。演算法的步驟如下: