1. 程式人生 > 實用技巧 >我的高精度模板

我的高精度模板

該模板來源於我搜集的資料(找不到來源了。。。)

我覺得挺好用的。

每天一遍,就能背下來

#include<bits/stdc++.h>
using namespace std;
const int MAX=100;
struct hp
{
    int num[MAX];
    
    hp & operator = (const char*);
    hp & operator = (int);
    hp();
    hp(int);

    // 以下運算子可以根據實際需要來選擇。
    bool operator > (const hp &) const
; bool operator < (const hp &) const; bool operator <= (const hp &) const; bool operator >= (const hp &) const; bool operator != (const hp &) const; bool operator == (const hp &) const; hp operator + (const hp &) const; hp operator - (const
hp &) const; hp operator * (const hp &) const; hp operator / (const hp &) const; hp operator % (const hp &) const; hp & operator += (const hp &); hp & operator -= (const hp &); hp & operator *= (const hp &); hp & operator /= (const
hp &); hp & operator %= (const hp &); }; //實現運算子的程式碼最好寫到結構體的外面。 //"<<"和">>"由於不是hp的成員,所以必須寫到結構體的外面。 //(2) 賦值和初始化 // num[0]用來儲存數字位數。另外,利用10000進位制可以節省空間和時間。 hp & hp::operator = (const char* c) { memset(num,0,sizeof(num)); int n=strlen(c),j=1,k=1; for (int i=1;i<=n;i++) { if (k==10000) j++,k=1; // 10000進位制,4個數字才算1位。 num[j]+=k*(c[n-i]-'0'); k*=10; } num[0]=j; return *this; } hp & hp::operator = (int a) { char s[MAX]; sprintf(s,"%d",a); return *this=s; } hp::hp() {memset(num,0,sizeof(num)); num[0]=1;} // 目的:宣告hp時無需顯式初始化。 hp::hp (int n) {*this = n;} // 目的:支援"hp a=1;"之類的程式碼。 //(3) 比較運算子 //小學時候學過怎麼比較兩個數的大小吧?現在,雖為高中生,小學知識卻從未過時…… // 如果位數不等,大小是可以明顯看出來的。如果位數相等,就需要逐位比較。 bool hp::operator > (const hp &b) const { if (num[0]!=b.num[0]) return num[0]>b.num[0]; for (int i=num[0];i>=1;i--) if (num[i]!=b.num[i]) return (num[i]>b.num[i]); return false; } bool hp::operator < (const hp &b) const {return b>*this;} bool hp::operator <= (const hp &b) const {return !(*this>b);} bool hp::operator >= (const hp &b) const {return !(b>*this);} bool hp::operator != (const hp &b) const {return (b>*this)||(*this>b);} bool hp::operator == (const hp &b) const {return !(b>*this)&&!(*this>b);} //(4) 四則運算 //如果沒學過豎式,或者忘了怎麼用豎式算數,那麼你就悲劇了…… //1. 加法和減法 // 注意:最高位的位置和位數要匹配。 hp hp::operator + (const hp &b) const { hp c; c.num[0] = max(num[0], b.num[0]); for (int i=1;i<=c.num[0];i++) { c.num[i]+=num[i]+b.num[i]; if (c.num[i]>=10000) // 進位 { c.num[i]-=10000; c.num[i+1]++; } } if (c.num[c.num[0]+1]>0) c.num[0]++; // 9999+1,計算完成後多了一位 return c; } hp hp::operator - (const hp &b) const { hp c; c.num[0] = num[0]; for (int i=1;i<=c.num[0];i++) { c.num[i]+=num[i]-b.num[i]; if (c.num[i]<0) // 退位 { c.num[i]+=10000; c.num[i+1]--; } } while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--; // 100000000-99999999 return c; } hp & hp::operator += (const hp &b) {return *this=*this+b;} hp & hp::operator -= (const hp &b) {return *this=*this-b;} //2. 乘法 hp hp::operator * (const hp &b) const { hp c; c.num[0] = num[0]+b.num[0]+1; for (int i=1;i<=num[0];i++) { for (int j=1;j<=b.num[0];j++) { c.num[i+j-1]+=num[i]*b.num[j]; // 和小學豎式的演算法一模一樣 c.num[i+j]+=c.num[i+j-1]/10000; // 進位 c.num[i+j-1]%=10000; } } while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--; // 99999999*0 return c; } hp & hp::operator *= (const hp &b) {return *this=*this*b;} //3. 除法 //高精度除法的使用頻率不太高。 //以下程式碼的缺陷是:如果b太大,運算速度會非常慢。該問題可以用二分查詢解決。 hp hp::operator / (const hp &b) const { hp c, d; c.num[0] = num[0]+b.num[0]+1; d.num[0] = 0; for (int i=num[0];i>=1;i--) { // 以下三行的含義是:d=d*10000+num[i]; memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2); d.num[0]++; d.num[1]=num[i]; // 以下迴圈的含義是:c.num[i]=d/b; d%=b; while (d >= b) { d-=b; c.num[i]++; } } while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--; // 99999999/99999999 return c;//求餘數 則返回d } hp hp::operator % (const hp &b) const { hp c, d; c.num[0] = num[0]+b.num[0]+1; d.num[0] = 0; for (int i=num[0];i>=1;i--) { // 以下三行的含義是:d=d*10000+num[i]; memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2); d.num[0]++; d.num[1]=num[i]; // 以下迴圈的含義是:c.num[i]=d/b; d%=b; while (d >= b) { d-=b; c.num[i]++; } } while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--; // 99999999/99999999 return d; } hp & hp::operator /= (const hp &b) {return *this=*this/b;} hp & hp::operator %= (const hp &b) {return *this=*this%b;} //4. 二分優化的除法 //高精度除法速度慢,就慢在上面的while (d>=b)處。如果我們用二分法去猜d/b的值,速度就快了。 /*hp hp::operator / (const hp & b) const { hp c, d; c.num[0] = num[0]+b.num[0]+1; d.num[0] = 0; for (int i=num[0];i>=1;i--) { // 以下三行的含義是:d=d*10000+num[i]; memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2); d.num[0]++; d.num[1]=num[i]; // 以下迴圈的含義是:c.num[i]=d/b; d%=b; 利用二分查詢求c.num[i]的上界。 // 注意,這裡是二分優化後除法和樸素除法的區別! int left=0, right=9999, mid; while (left < right) { mid = (left+right)/2; if (b*hp(mid) <= d) left=mid+1; else right=mid; } c.num[i]=right-1; d=d-b*hp(right-1); } while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--; // 99999999/99999999 return c; // 求餘數就改成return d; }*/ //(5) 輸入/輸出 //有了這兩段程式碼,就可以直接用cout和cin輸出、輸入高精度數了。 ostream & operator << (ostream & o, hp &n) { o<<n.num[n.num[0]]; for (int i=n.num[0]-1;i>=1;i--) { o.width(4); o.fill('0'); o<<n.num[i]; } return o; } istream & operator >> (istream & in, hp &n) { char s[MAX]; in>>s; n=s; return in; } int main() { }
My 模板