?? tlargefloat.cpp
字號:
#include "TLargeFloat.h"
#include "assert.h"
#include <math.h>
#include <iostream>
bool TLargeFloat::FloatIsInteger(long double fValue)//浮點數是否為可表示整數
{
return (TMaxInt(floor(fValue))==fValue);
}
unsigned int TLargeFloat::DigitsSize(unsigned int uiDigitsLength)
{
if (!(uiDigitsLength>=1))
{
throw TException("ERROR:TLargeFloat::DigitsSize()");
}
return (uiDigitsLength+(em10Power-1))/em10Power;//計算出需要的數組大小
}
TLargeFloat::TLargeFloat(long double DefultFloatValue,const TDigits& DigitsLength)
:m_Digits(DigitsSize(DigitsLength.GetDigits()),0)
{
m_Exponent=0;
m_Sign=0;
*this=DefultFloatValue;
}
TLargeFloat::TLargeFloat(long double FloatValue,const TCharacter&)//內部使用 浮點數轉化為 TLargeFloat,并采用默認精度
:m_Digits(DigitsSize(emLongDoubleDigits),0)
{
m_Exponent=0;
m_Sign=0;
*this=FloatValue;
}
TLargeFloat::TLargeFloat(const SelfType& Value)
:m_Digits(Value.m_Digits)
{
m_Exponent=Value.m_Exponent;
m_Sign=Value.m_Sign;
}
TLargeFloat::SelfType& TLargeFloat::operator = (const SelfType& Value)
{
m_Digits=Value.m_Digits;
m_Exponent=Value.m_Exponent;
m_Sign=Value.m_Sign;
return *this;
}
void TLargeFloat::SetDigitsLength(unsigned int uiDigitsLength)//重新設置10進制有效位數
{
m_Digits.resize(DigitsSize(uiDigitsLength),0);
}
unsigned int TLargeFloat::GetDigitsLength() const//返回當前的10進制有效位數
{
return m_Digits.size()*em10Power;
}
void TLargeFloat::Clear()
{
//清零
int size=m_Digits.size();
for (int i=0;i<size;++i)
m_Digits[i]=0;
m_Exponent=0;
m_Sign=0;
}
TLargeFloat::SelfType& TLargeFloat::operator = (long double fValue)
{
Clear();
if (0==fValue)
{
//do nothing;
}
else
{
if (fValue>0)
m_Sign=1;
else
{
m_Sign=-1;
fValue=-fValue;
}
if (FloatIsInteger(fValue))//對 為"可表示整數" 的浮點數 進行特殊處理 無誤差轉換
{
long double tf=fValue;
int n=0;
for (;;++n)
{
if (0==tf) break;
tf/=emBase;
tf=floor(tf);
}
m_Exponent=n*em10Power;
for (int i=0;i<n;++i)
{
m_Digits[n-1-i]=Int32bit(TMaxInt(fValue)%emBase);
fValue=floor(fValue/emBase);
}
}
else//一般的浮點數 轉化中可能產生小的誤差
{
m_Exponent=int(floor(log10(fValue)))+1;//得到10為底的指數
fValue/=pow(10.0,(long double)(m_Exponent.AsInt()));
int size=m_Digits.size();
int minsize=Private_::min(size,emLongDoubleDigits/em10Power+1);
for (int i=0;i<minsize;++i)//得到小數位
{
if (0==fValue) break;
fValue*=emBase;
Int32bit IValue=Int32bit(floor(fValue));
fValue-=IValue;
m_Digits[i]=IValue;
if (i==minsize-1)
{
if (fValue*emBase*2>=emBase)//四舍五入
{
m_Digits[i]+=1;
for (int j=i;j>0;--j)
{
if (m_Digits[j]>=emBase)//進位
{
m_Digits[j-1]+=1;
m_Digits[j]-=emBase;
}
else
break;
}//for j
}//if
}//if
}
}//for i
}
Canonicity();
return *this;
}
long double TLargeFloat::AsFloat() const
{
//
if ( ((m_Exponent.AsInt())>=emLongDoubleMaxExponent)
||((m_Exponent.AsInt())<=emLongDoubleMinExponent) )
{
throw TException("ERROR:TLargeFloat::AsFloat()");
}
if (m_Sign==0) return 0;
long double result=m_Sign;
result*=pow(10,double(m_Exponent.AsInt()));
long double r=1;
long double Sum=0;
int m_CalcSize=m_Digits.size();
for (int i=0;i<m_CalcSize;++i)//得到小數位
{
r/=emBase;
if (r==0) break;
Sum+=(m_Digits[i]*r);
}
return result*Sum;
}
void TLargeFloat::MoveLeft10Power(TMaxInt MoveCount)
{
m_Exponent-=MoveCount;
TMaxInt i=MoveCount/em10Power;
TMaxInt iMoveCount= MoveCount%em10Power;
//完成大的移動
int m_CalcSize=m_Digits.size();
if (i>=m_CalcSize)
{
Clear();
return;
}
else if (i>0) //左移i
{
for (int j=0;j<m_CalcSize-i;++j)
m_Digits[j]=m_Digits[int(j+i)];
for (int k=int(m_CalcSize-i);k<m_CalcSize;++k)
m_Digits[k]=0;
}
if (iMoveCount>0) //完成小的移動
{
int iMul=1;
for (int k=0;k<iMoveCount;++k) iMul*=10;
for (int i=m_CalcSize-1;i>=0;--i)
{
m_Digits[i]*=iMul;
}
for (int j=m_CalcSize-1;j>=1;--j)
{
if (m_Digits[j]>emBase)
{
m_Digits[j-1]+=m_Digits[j]/emBase;
m_Digits[j]%=emBase;
}
}
}
}
void TLargeFloat::MoveRight10Power(TMaxInt MoveCount)
{
m_Exponent+=MoveCount;
TMaxInt i=MoveCount/em10Power;
TMaxInt iMoveCount= MoveCount%em10Power;
//完成大的移動
int m_CalcSize=m_Digits.size();
if (i>=m_CalcSize)
{
Clear();
return;
}
else if (i>0) //右移i
{
for (int j=m_CalcSize-1;j>=i;--j)
m_Digits[j]=m_Digits[int(j-i)];
for (int k=0;k<i;++k)
m_Digits[k]=0;
}
if (iMoveCount>0) //完成小的移動
{
Int32bit iDiv=1;
for (int j=0;j<iMoveCount;++j) iDiv*=10;
for ( i=0;i<m_CalcSize-1;++i)
{
m_Digits[int(i)+1]+=(m_Digits[int(i)]%iDiv)*emBase;
m_Digits[int(i)]/=iDiv;
}
if (m_CalcSize>=1)
m_Digits[m_CalcSize-1]/=iDiv;
}
}
void TLargeFloat::Canonicity()
{
//規格化 小數部分
//規格化的數滿足的條件:小數部分的值 小于1.0,大于等于0.1;
if (m_Sign==0)
{
Clear();
return;
}
int size=m_Digits.size();
if (m_Digits[0]>=emBase)//是否需要右移1
{
m_Exponent+=em10Power;
for (int j=size-1;j>=2;--j)
m_Digits[j]=m_Digits[j-1];
if (size>=2) m_Digits[1]=m_Digits[0] % emBase;
m_Digits[0]/=emBase;
}
//考慮左移
int i=0;
int iMoveCount=0;
for (;i<size;++i)//尋找第一個不為零的位i
{
if (m_Digits[i]>0)
{
Int32bit iBase=emBase;//iMoveCount 需要移動的十進制位數
for (;iMoveCount<em10Power;++iMoveCount)
{
iBase/=10;
if (m_Digits[i]>=iBase) break;
}
break;
}
}
MoveLeft10Power(i*em10Power+iMoveCount);
}
std::string TLargeFloat::DigitToString(Int32bit iDigit)
{
char buffer[40];
for (int j=0;j<40;++j) buffer[j]=0;
_itoa(iDigit, buffer,10);
std::string result(buffer);
assert(em10Power>=result.size());
result=std::string(em10Power-result.size(),'0')+result;
return result;
}
std::string TLargeFloat::AsString() const//轉換為字符串
{
//沒有優化
if (m_Sign==0)
return "0";
else
{
std::string result;
if (m_Sign<0)
result="-0.";
else
result="0.";
int size=m_Digits.size();
for (int i=0;i<size;++i)
{
result+=DigitToString(m_Digits[i]);
}
if (m_Exponent.AsInt()!=0)
{
result+='e';
if (m_Exponent.AsInt()<0) result+='-';
char buffer[40];
//_i64toa(Private_::abs(m_Exponent.AsInt()), buffer,10);//__int64
_itoa(Private_::abs(m_Exponent.AsInt()), buffer,10);
result+=buffer;
}
return result;
}
}
void TLargeFloat::Chs()//求負
{
m_Sign*=(-1);
}
void TLargeFloat::Abs()//絕對值
{
if (m_Sign!=0) m_Sign=1;
}
void TLargeFloat::swap(SelfType& Value)
{
m_Digits.swap(Value.m_Digits);
std::swap(m_Sign,Value.m_Sign);
std::swap(m_Exponent,Value.m_Exponent);
}
//////////////
void TLargeFloat::toEqExponent(SelfType& x,SelfType& y)//對齊小數點
{
ExpInt MoveCount=x.m_Exponent;
MoveCount-=y.m_Exponent;
if (MoveCount.AsInt()<0) MoveCount=ExpInt(-MoveCount.AsInt());
if (x.m_Exponent.AsInt()>y.m_Exponent.AsInt())
{
y.MoveRight10Power(MoveCount.AsInt());
y.m_Exponent=x.m_Exponent;
}
else if(x.m_Exponent.AsInt()<y.m_Exponent.AsInt())
{
x.MoveRight10Power(MoveCount.AsInt());
x.m_Exponent=y.m_Exponent;
}
}
void TLargeFloat::Abs_Add(const SelfType& Value)//絕對值加法
{
SelfType Right(Value);
Abs();
Right.Abs();
toEqExponent(Right,*this);//小數點對齊
SetSameSizeMax(Right,*this);
int m_CalcSize=m_Digits.size();
m_Digits[0]+=Right.m_Digits[0];
for (int j=m_CalcSize-1;j>=1;--j)
{
m_Digits[j]+=Right.m_Digits[j];
if (m_Digits[j]>=emBase)//進位
{
m_Digits[j-1]+=1;
m_Digits[j]-=emBase;
}
}
if (m_Digits[0]>=emBase)
Canonicity();
}
void TLargeFloat::Abs_Sub_Abs(const SelfType& Value)//絕對值減法
{
SelfType Right(Value);
Abs();
Right.Abs();
toEqExponent(Right,*this);//小數點對齊
SetSameSizeMax(Right,*this);
int comResult=Compare(Right);
if (comResult==0)
{
Clear();
return;
}
if (comResult<0)
swap(Right);
int m_CalcSize=m_Digits.size();
for (int j=m_CalcSize-1;j>=0;--j)
{
m_Digits[j]-=Right.m_Digits[j];
if (m_Digits[j]<0)//借位
{
m_Digits[j-1]-=1;//j-1不可能超界
m_Digits[j]+=emBase;
}
}
if (m_Digits[0]*10<emBase)
Canonicity();
}
///////////////////
TLargeFloat::SelfType& TLargeFloat::operator += (const SelfType& Value)
{
if (Value.m_Sign==0)
return (*this);
else if (m_Sign==0)
return (*this)=Value;
else if (m_Sign==Value.m_Sign)
{
Int32bit oldSign=m_Sign;
Abs_Add(Value);
m_Sign=oldSign;
}
else
{
SelfType x(Value);
x.Chs();
*this-=(x);
}
return *this;
}
TLargeFloat::SelfType& TLargeFloat::operator -= (const SelfType& Value)
{
if (Value.m_Sign==0)
return (*this);
else if (m_Sign==0)
{
(*this)=Value;
this->Chs();
return (*this);
}
else if (m_Sign==Value.m_Sign)
{
int comResult=Compare(Value);
if (comResult==0)
{
Clear();
}
else
{
Abs_Sub_Abs(Value);
m_Sign=comResult;
}
}
else
{
SelfType x(Value);
x.Chs();
*this+=(x);
}
return *this;
}
int TLargeFloat::Compare(const SelfType& Value) const//*this>Value 返回1,小于返回-1,相等返回0
{
//
if (m_Sign>Value.m_Sign)
return 1;
else if(m_Sign<Value.m_Sign)
return -1;
else if(m_Sign==0)//m_Sign==Value.m_Sign
return 0;
//m_Sign==Value.m_Sign
if (m_Exponent.AsInt()>Value.m_Exponent.AsInt())
{
if (m_Sign<0)
return -1;
else
return 1;
}
else if (m_Exponent.AsInt()<Value.m_Exponent.AsInt())
{
if (m_Sign<0)
return 1;
else
return -1;
}
else//(m_Exponent==Value.m_Exponent)
{
int sizeS=m_Digits.size();
int sizeV=Value.m_Digits.size();
int size=Private_::min(sizeS,sizeV);
int result=0;
for (int i=0;i<size;++i)
{
if (m_Digits[i]>Value.m_Digits[i])
{
result=1;
break;
}
else if (m_Digits[i]<Value.m_Digits[i])
{
result=-1;
break;
}
}
if (result==0)
{ //繼續比較 處理尾部
if (sizeS>sizeV)
{
for (int i=sizeV;i<sizeS;++i)
{
if (m_Digits[i]>0)
{
result=1;
break;
}
}
}
else if (sizeS<sizeV)
{
for (int i=sizeS;i<sizeV;++i)
{
if (Value.m_Digits[i]>0)
{
result=-1;
break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -