1. 程式人生 > >高精度帶符號整數演算法

高精度帶符號整數演算法

本部落格是 高精度無符號整數演算法 的延伸版本,請讀者在食用前序文章後食用本篇效果更佳。

高精度的寫法

同無符號的一樣,我們仍採用struct封裝,但與之前不同的是,我們新定義一個f表示正負。

struct Wint:vector<int>
{
	int f=1;
};

然後改下建構函式

    Wint(int n=0)
    {
    	if(n<0)n*=f=-1;
        push_back(n);
    }

不再過多解釋建構函式寫法,只是這裡要判斷收到的n的正負。
然後是check函式。

    Wint&
check() { while(!empty()&&!back())pop_back(); if(empty()){f=1;return *this;} if(back()<0) { f*=-1; for(int i=0; i<size(); ++i) (*this)[i]*=-1; } for(int i=1; i<size(); ++i) { while((*this)[i-1]<
0) { int j=i; while((*this)[j]<=0&&j<size())++j; while(j>=i) { --(*this)[j]; (*this)[--j]+=10; } } (*this)[i]+=(*this)[i-1]/10; (*this)[i-1]%=10; while
(!empty()&&!back())pop_back(); if(empty()){f=1;return *this;} } while(back()>=10) { push_back(back()/10); (*this)[size()-2]%=10; } if(back()<0)f*=-1,(*this)[size()-1]*=-1; return *this; }

那麼整體的struct就長這樣

struct Wint:vector<int>
{
	int f=1;
    Wint(int n=0)
    {
    	if(n<0)n*=f=-1;
        push_back(n);
    }
    Wint& check()
    {
        while(!empty()&&!back())pop_back();
        if(empty()){f=1;return *this;}
        if(back()<0)
        {
    		f*=-1;
    		for(int i=0; i<size(); ++i)
    			(*this)[i]*=-1;
        }
        for(int i=1; i<size(); ++i)
        {
        	while((*this)[i-1]<0)
	        {
	            int j=i;
	            while((*this)[j]<=0&&j<size())++j;
	            while(j>=i)
	            {
	                --(*this)[j];
	                (*this)[--j]+=10;
	            }
	        }
            (*this)[i]+=(*this)[i-1]/10;
            (*this)[i-1]%=10;
            while(!empty()&&!back())pop_back();
        	if(empty()){f=1;return *this;}
        }
        while(back()>=10)
        {
            push_back(back()/10);
            (*this)[size()-2]%=10;
        }
        if(back()<0)f*=-1,(*this)[size()-1]*=-1;
        return *this;
    }
};

所有的運算子過載可以參見我的 過載運算子和過載函式 部落格

輸入輸出運算子

istream& operator>>(istream &is,Wint &n)
{
    string s;
    is>>s;
    n.clear();
    for(int i=s.size()-1; i>=0; --i)
    {
    	if(s[i]=='-')
    	{
    		n.f=-1;
    		continue;
    	}
    	n.push_back(s[i]-'0');
    }
    return is;
}
ostream& operator<<(ostream &os,const Wint &n)
{
    if(n.empty()){os<<0;return os;}
	if(n.f==-1)os<<"-";
    for(int i=n.size()-1; i>=0; --i)os<<n[i];
    return os;
}

直接增加"-"的判斷即可。

關係運算符

正如之前的,我們只寫高精度之間的比較~~,如果我們要比較一個高精度和另一個整數,可以同之前所述採用stringstream傳(此條因太過毒瘤筆者被Diss到爆而去掉,感興趣的讀者可以自己瞭解下stringstream)~~。

bool operator!=(const Wint &a,const Wint &b)
{
	if(a.f!=b.f)return 1;
    if(a.size()!=b.size())return 1;
    for(int i=a.size()-1; i>=0; --i)
        if(a[i]!=b[i])return 1;
    return 0;
}
bool operator==(const Wint &a,const Wint &b)
{
    return !(a!=b);
}
bool operator<(const Wint &a,const Wint &b)
{
	if(a.f!=b.f)return a.f<b.f;
    if(a.size()!=b.size())return a.size()<b.size();
    for(int i=a.size()-1; i>=0; --i)
        if(a[i]!=b[i])return a[i]<b[i];
    return 0;
}
bool operator>(const Wint &a,const Wint &b)
{
    return b<a;
}
bool operator<=(const Wint &a,const Wint &b)
{
    return !(a>b);
}
bool operator>=(const Wint &a,const Wint &b)
{
    return !(a<b);
}

加上判斷f即可。

單目運算子與abs函式

Wint operator-(Wint a)
{
	if(~a.f)a.f=-1;
	else a.f=1;
	return a.check();
} 
Wint abs(Wint a)
{
	if(a<0)return -a;
	else return a;
} 

對於-運算子,我們改變符號即可。
對於abs函式,我們分段返回即可。

邏輯運算子

此內容已因筆者過於蒟蒻或毒瘤而被Diss到爆炸,現已劃線。

//bool operator!(Wint &n)
//{
//	n.check();
//	return n==0;
//}
//bool operator~(Wint &n)
//{
//	n.check();
//	return n!=-1;
//}
//bool operator&&(Wint &a,Wint &b)
//{
//	a.check();b.check();
//	if(!a)return 0;
//	if(!b)return 0;
//	return 1;
//}
//bool operator||(Wint &a,Wint &b)
//{
//	a.check();b.check();
//	if(a>0)return 1;
//	if(b>0)return 1;
//	return 0;
//}

即使加上符號也十分的簡單對不對。。。

雙目算術、賦值和自增自減運算子

Wint& operator+=(Wint &a,const Wint &b)
{
	Wint c=b;
    if(a.size()<c.size())a.resize(c.size());
    if(a<0&&c>0)
    {
    	if(abs(a)<abs(c))
    	{
    		swap(a,c);
    	}
    }
    else if(a>0&&c<0)
    {
    	if(abs(a)<abs(c))
    	{
    		swap(a,c);
    	}
    }
    for(int i=0; i!=b.size();++i)a[i]+=c[i]*((a.f==c.f)?1:-1);
    return a.check();
}
Wint operator+(Wint a,const Wint &b)
{
    return a+=b;
}
Wint& operator++(Wint &n)
{
	n+=1;
	return n.check();
}
Wint operator++(Wint &n,int flag)
{
	Wint tmp=n;
	n+=1;
	n.check();
	return tmp;
}
Wint& operator-=(Wint &a,const Wint b)
{
	return a+=-b;
}
Wint operator-(Wint a,const Wint &b)
{
    return a-=b;
}
Wint& operator--(Wint &n)
{
	n-=1;
	return n.check();
}
Wint operator--(Wint &n,int flag)
{
	Wint tmp=n;
	n-=1;
	n.check();
	return tmp;
}

有了符號,加減就可以一起處理了。

Wint operator*(const Wint &a,const Wint &b)
{
    Wint n;
    if(a.f!=b.f)n.f=-1;
    else n.f=1;
    n.assign(a.size()+b.size()-1,0);
    for(int i=0; i!=a.size(); ++i)
        for(int j=0; j!=b.size(); ++j)
            n[i+j]+=a[i]*b[j];
    return n.check();
}
Wint& operator*=(Wint &a,const Wint &b)
{
    return a=a*b;
}
Wint divmod(Wint &a,const Wint &b)
{
    Wint ans,tmp=b;
    int af=a.f,tmpf=tmp.f;
    a.f=tmp.f=1;
    for(int t=a.size()-tmp.size(); a>=tmp; --t)
    {
        Wint d;
        d.assign(t+1,0);
        d.back()=1;
        Wint c=tmp*d;
        while(a>=c)
        {
            a-=c;
            ans+=d;
        }
    }
    if(af!=tmpf)ans.f=-1;
    else ans.f=1;
    a.f=af,tmp.f=tmpf;
    return ans.check();
}
Wint operator/(Wint a,const Wint &b)
{
    return divmod(a,b);
}
Wint& operator/=(Wint &a,const Wint &b)
{
    return a=a/b;
}
Wint& operator%=(Wint &a,const Wint &b)
{
    divmod(a,b);
    return a;

            
           

相關推薦

精度符號整數演算法

本部落格是 高精度無符號整數演算法 的延伸版本,請讀者在食用前序文章後食用本篇效果更佳。 高精度的寫法 同無符號的一樣,我們仍採用struct封裝,但與之前不同的是,我們新定義一個f表示正負。 struct Wint:vector<int> { int f=1;

精度符號整數演算法

高精度的寫法 我們為了方便後來的操作,可以先使用一個struct封裝內容物。 我們可以在宣告一個struct的時候自動宣告一個vector作為整體型別。 struct Wint:vector<int> { }; 我們可以寫一個建構函式 Wint(int n

精度計算-大整數乘法

大整數乘法 問題描述 求兩個不超過 200 位的非負整數的積。 輸入資料 有兩行,每行是一個不超過 200 位的非負整數,沒有多餘的前導 0。 輸出要求 一行,即相乘後的結果。結果裡不能

C/C++精度運算(大整數運算)詳解(含壓位)

1.高精度加法1.1 高精度加法        高精度運算的基本運算就是加和減。和算數的加減規則一樣,模擬豎式計算,考慮錯位運算與進位處理。下面是我老師給的程式碼,目前比網上其他的程式碼要精簡和巧妙。#include <cstdio> #include <c

精度】大整數

把這段模版敲上,直接像定義int一樣定義變數就行了,支援加減和賦值、輸入、輸出(只能用cin,cout) struct BigInteger{ int size,num[1000]; BigInteger(){ size=0;

c++精度演算法-大整數運算

#include<iostream> #include<vector> #include<cstring> using namespace std; struct BigInteger{ static const int BASE=100000000;

實用演算法實現-第 24 篇 精度整數運算

24.1.1   例項 PKU JudgeOnline, 1503, Integer Inquiry. 24.1.2   問題描述 給定一組超長的正整數(100位),求出它們的和。 24.1.3   輸入 123456789012345678901234567890

c++ 無符號bigint精度整數

c++ 無符號bigint高精度大整數 此程式碼除了減法和乘法以外均參考了劉汝佳的《演算法競賽入門經典第二版》,親測DevC++可以編譯通過。程式碼在codevs( codevs.cn )上通過高精度全部題目。POWERED BY PHANTOM 大神勿噴,希望大家支援! #in

Java中的精度整數精度小數

整數測試 div string pac 高精 int trac print log 在實際編碼中,會遇到很多高精度的事例,比如,在計算金錢的時候就需要保留高精度小數,這樣計算才不會有太大誤差: 在下面的代碼中,我們驗證了,當兩個float型的數字相加,得到的結果和我們的預期

把虛擬教練回家,「EuMotus」想用AI實現精度運動反饋系統

https://36kr.com/p/5089139.html 無需穿戴裝置,只需一個紅外攝像頭和+已安裝好EuMotus專利軟體的手提電腦 由政府主導的高達2200億美金的健身與運動支出,15%的健身俱樂部年增長率,46%的中國年輕人正在使用健身器材與健身軟體。這是美國IBIS此前釋出的關於中國體

精度計算_大整數_加_減_乘_除_int型_模板_基於deque

下面給出的是大整數加, 減, 乘, 除int型的模板: 約定: 下面的模板實現中a, b均為HEX進位制數, 且a[0]為a的最高位 const int HEX = 1e9;//運算採取的進位制 deque<int> operator + (const deque<i

精度計算_大整數_加_減_乘_除_大整數_基於vector_高效計算_模板

    本文給出的是, 相對偏重於計算效率的大整數運算模板, 程式碼數量整體多餘前面介紹的基於deque的大整數計算模板, 當然如果僅需要大整數與int型運算, 那麼請參考本人有關大整數和int型計算的部落格.     為何稱本文給出的高效計算的模板,

精度整數(俞書)

完成了高精度整數的加減乘除以及取模運算 附上程式碼: #include<bits/stdc++.h> using namespace std; const int ten[4]={1,10,100,1000}; const int maxl=1000; struct Bi

資料結構學習(一):精度演算法

高精度演算法,屬於處理大數字的數學計算方法。在一般的科學計算中,會經常算到小數點後幾百位或者更多,當然也可能是幾千億幾百億的大數字。一般這類數字我們統稱為高精度數,高精度演算法是用計算機對於超大資料的一種模擬加,減,乘,除,乘方,階乘,開方等運算。對於非常龐大的數字無法在計算機中正常儲存

精度演算法模板索引

1、四則運算 高精加高精 高精減高精 高精乘高精(FFT優化) 高精除高精 2、四則運算 高精加低精 高精減低精 高精乘低精 高精除低精 3、其他運算 高精取模高精 高精取模低精 高精比較

上海交大OJ 精度整數

1014. 高精度加法 Description 輸入2個整數a和b,輸出a+b。 Input Format 輸入有兩行,第一行a,第二行b。 0≤a,b≤10 100000  0≤a,b≤10100000 。 Output Format 輸出

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

[C++]精度演算法

目錄 高精度加法    高精度減法    高精度乘法    高精度除法    高精度階乘 高精度加法 用程式來模擬豎式加法即可,注意在輸出的時候除去多餘的前導零

JAVA精度演算法 BigInteger用法詳解 大數四則運算

在用C或者C++處理大數時感覺非常麻煩,但是在Java中有兩個類BigInteger和BigDecimal分別表示大整數類和大浮點數類,至於兩個類的物件能表示最大範圍不清楚,理論上能夠表示無線大的數,只要計算機記憶體足夠大。 這兩個類都在java.math.*包中,因此每次必須在開頭處引用該包。

【機試練習】【C++】精度/大整數運算

#include<cstdio> #include<cstring> #include<cmath> using namespace std; const int MAXLEN = 10000; // 最大支援數值長度