自己动手打造“超高精度浮点数类”
HouSisong@GMail.com
tag:PI,超高精度浮点数,TLargeFloat,FFT乘法,二分乘法,牛顿迭代法,borwein四次迭代,AGM二次迭代
很多人可能都想自己写一个能够执行任意精度计算的浮点数;:D我写的第一个程序就是用qbasic计算自然数e到100万位(后来计算PI); 这里有一个C++类的实现TLargeFloat,它能够执行高精度的浮点数运算;演示代码里面有一个计算PI的Borwein四次迭代式和一个AGM二次迭代式(我用它计算出了上亿位的PI小数位:)
源代码的简要导读文章: http://blog.csdn.net/housisong/archive/2007/12/24/1965652.aspx
(2007.12.14 进行了一些速度优化,添加了FFT实现的大数乘法; 进行高精度(百万千万位)运算时的速度提高了很多!)
(2007.11.29 对代码进行了一次梳理,添加了二分法实现的大数乘法,改进了除法和开方运算;速度提高很多)
(2007.11.20 对乘法进行了一点小的优化,速度提高了些; 修正了两处bug,在MoveLeft10Power和MulInt函数中的进位问题)
类的声明文件:TLargeFloat.h
/////
// TLargeFloat.h: interface for the TLargeFloat class.
// 超高精度浮点数类TLargeFloat
// 2004.03.28 by HouSisong@GMail.com
//
// Update 2004.03.31 by HouSisong
// ......
// Update 2007.11.29-12.20 by HouSisong 重构一遍,速度加快很多,我用它计算了上亿位的PI值:)
#ifndef _TLARGE_FLOAT_H__INCLUDED_
#define _TLARGE_FLOAT_H__INCLUDED_
#include <vector>
#include <sstream>
#include <string>
#include <Exception>
#include <limits>
class TLargeFloat;//超高精度浮点数类TLargeFloat
class TLargeFloatException;// 超高精度浮点数异常类
// 改进方向:
// 1.强力优化ArrayMUL数组乘运算(当前实现了二分法和FFT算法):
// a.将实数按齐偶作为复数进行傅立叶变换的算法实现,加快乘法速度
// b.实现混合基的傅立叶变换,加快乘法速度
// c.考虑用x87的10byte浮点数实现FFT以减小误差从而增大FFT能够计算的最大位数限制
// d.用SSE2等优化快速复利叶变换,加快乘法速度
// e.或者将傅立叶变换替换为数论变换的实现(使用整数)
// 2.内部使用8位(或9位)十进制来实现,节约内存;或者2进制的底数(这样的话,输出函数就会麻烦一些了)
// 3.添加新的基本运算函数,如:指数运算power、对数运算log、三角函数sin,cos,tan等
// 注意:如果浮点数与TLargeFloat进行混合运算, 可能会产生误差(有效位数会受到浮点数影响);
// 整数 或 为可表示整数的浮点数 参与运算不会产生误差;
// 对于很大的整数或者有小数位的浮点数,建议用字符串的形式转换为超高精度浮点数(不会引入误差)
//void ArrayMUL(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize);// 数组乘, 需要优化的首要目标
//超高精度浮点数异常类 //TLargeFloat运算中出现错误的时候会抛出该类型的异常
class TLargeFloatException :public std::runtime_error
{
public :
TLargeFloatException(const char * Error_Msg) :runtime_error(Error_Msg){}
virtual ~TLargeFloatException() throw () {}
};
// TCatchIntError只是对整数类型TInt进行的一层包装
// 超高精度浮点数类的指数运算时使用
// 设计TCatchIntError是为了当整数运算超出值域的时候,抛出异常
//template<要包装的整数类型,超界时抛出的异常类型,TInt最小值,TInt最大值>
template <typename TInt,typename TException,TInt MinValue,TInt MaxValue>
class TCatchIntError
{
private :
typedef TCatchIntError<TInt,TException,MinValue,MaxValue> SelfType;
TInt m_Int;
inline SelfType& inc(const TInt& uValue)
{
if ( (uValue<0)||(uValue>MaxValue)||(MaxValue-uValue< m_Int) )
throw TException("ERROR:TCatchIntError::inc(); " );
m_Int+= uValue;
return (*this );
}
inline SelfType& dec(const TInt& uValue)
{
if ( (uValue<0)||(uValue>MaxValue)||(MinValue+uValue> m_Int) )
throw TException("ERROR:TCatchIntError::dec()" );
m_Int-= uValue;
return (*this );
}
inline SelfType& mul(const TInt& iValue)
{
if (iValue==0 )
m_Int=0 ;
else
{
TInt tmp =m_Int* iValue;
if ( (iValue<MinValue)||(iValue>MaxValue)||(tmp<MinValue)||(tmp>MaxValue)||((tmp/iValue)!= m_Int) )
throw TException("ERROR:TCatchIntError::mul(); " );
m_Int= tmp;
}
return (*this );
}
public :
inline TCatchIntError() :m_Int(0 ){ }
inline TCatchIntError(const TInt& Value) :m_Int(0) { (*this)+= Value;}
inline TCatchIntError(const SelfType& Value) :m_Int(0) { (*this)+= (Value.m_Int); }
inline const TInt& AsInt() const { return m_Int; }
inline SelfType& operator +=(const TInt& Value) //throw(TLargeFloatException)
{ if (Value<0) return dec(- Value);
else return inc(Value); }
inline SelfType& operator -=(const TInt& Value) //throw(TLargeFloatException)
{ if (Value<0) return inc(- Value);
else return dec(Value); }
inline SelfType& operator *=(const TInt& Value) //throw(TLargeFloatException)
{ return mul(Value); }
inline SelfType& operator +=(const SelfType& Value) { return (*this)+=(Value.m_Int); }//throw(TLargeFloatException)
inline SelfType& operator -=(const SelfType& Value) { return (*this)-=(Value.m_Int); }//throw(TLargeFloatException)
inline SelfType& operator *=(const SelfType& Value) { return (*this)*=(Value.m_Int); }//throw(TLargeFloatException)
};
// 指数部分使用的整数类型 填写编译器支持的较大的整数类型
//typedef __int64 TMaxInt; // type long long TMaxInt;
// const TMaxInt TMaxInt_MAX_VALUE = TMaxInt(9223372036854775807);
//const TMaxInt TMaxInt_MIN_VALUE = - TMaxInt_MAX_VALUE;
typedef long TMaxInt;
const TMaxInt TMaxInt_MAX_VALUE = 2147483647 ;
const TMaxInt TMaxInt_MIN_VALUE = - TMaxInt_MAX_VALUE;
//小数部分使用的整数类型 32bit位的整数类型
typedef long TInt32bit;
const TInt32bit TInt32bit_MAX_VALUE = 2147483647 ;
const TInt32bit TInt32bit_MIN_VALUE = - TInt32bit_MAX_VALUE;
//超高精度浮点数类
class TLargeFloat
{
public :
//一些常量和类型定义
typedef std::vector<TInt32bit> TArray;//小数位使用的数组类型
enum { em10Power =4, //数组为10000进制,
emBase =10000, //数组的一个元素对应4个十进制位
emLongDoubleDigits =std::numeric_limits<long double>::digits10,//long double的10进制有效精度
emLongDoubleMaxExponent =std::numeric_limits<long double>::max_exponent10,//long double的最大10进制指数
emLongDoubleMinExponent =std::numeric_limits<long double>::min_exponent10 };//long double的最小10进制指数
typedef TLargeFloatException TException;
typedef TCatchIntError<TMaxInt,TException,TMaxInt_MIN_VALUE,TMaxInt_MAX_VALUE> TExpInt;//指数类型
typedef TLargeFloat SelfType;
public :
class TDigits//TDigits用来设置TLargeFloat的精度;//增加这个类是为了避免TLargeFloat的构造函数的可能误用
{
private :
unsigned long m_DigitsArraySize;
public :
explicit TDigits(const long uiDigitsLength)
{ if (uiDigitsLength<=0) throw TException("ERROR:TLargeFloat::TDigits()" );
m_DigitsArraySize=(uiDigitsLength+em10Power-1)/ em10Power; }
inline const unsigned long GetDigitsArraySize() const { return m_DigitsArraySize; }
};
TLargeFloat(const SelfType& Value);
explicit TLargeFloat(const long double DefultValue);//默认浮点精度 //注意:转换可能存在小的误差
explicit TLargeFloat(const long double DefultValue,const TDigits& DigitsLength);//TDigits 十进制有效位数 //注意:转换可能存在小的误差
explicit TLargeFloat(const char* strValue);//使用字符串本身的精度
explicit TLargeFloat(const char* strValue,const TDigits& DigitsLength);
explicit TLargeFloat(const std::string& strValue);
explicit TLargeFloat(const std::string& strValue,const TDigits& DigitsLength);
long double AsFloat() const;//转化为浮点数
std::string AsString() const;//转换为字符串
void SetDigitsLength(const TDigits& DigitsLength); //重新设置10进制有效位数
inline void SetDigitsLength(const long uiDigitsLength) { SetDigitsLength(TDigits(uiDigitsLength)); }
unsigned long GetDigitsLength() const;//返回当前的10进制有效位数
void Swap(SelfType& Value);//交换值
void Zero(); //设置为0
inline void StrToLargeFloat(const std::string& strValue) { sToLargeFloat(strValue); }
inline void StrToLargeFloat(const char* strValue) { sToLargeFloat(std::string (strValue)); }
SelfType& operator = (const SelfType& Value);
SelfType& operator = (long double fValue); //注意:转换可能存在小的误差
inline const SelfType operator - () const { SelfType temp(*this); temp.Chs(); return temp; }//求负
inline const SelfType& operator + () const { return (*this); }//求正
SelfType & operator += (const SelfType& Value);
SelfType& operator -= (const SelfType& Value);
inline SelfType& operator += (long double fValue) { return (*this)+= TLargeFloat(fValue); }
inline SelfType& operator -= (long double fValue) { return (*this)-= TLargeFloat(fValue); }
friend inline const TLargeFloat operator + (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); return temp+= y; }
friend inline const TLargeFloat operator - (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); return temp-= y; }
friend inline const TLargeFloat operator + (const TLargeFloat& x,long double y) { TLargeFloat temp(x); return temp+= y; }
friend inline const TLargeFloat operator - (const TLargeFloat& x,long double y) { TLargeFloat temp(x); return temp-= y; }
friend inline const TLargeFloat operator + (long double x,const TLargeFloat& y) { return y+ x; }
friend inline const TLargeFloat operator - (long double x,const TLargeFloat& y) { return -(y- x); }
SelfType& operator *= (long double fValue);
SelfType& operator *= (const SelfType& Value);
friend inline const TLargeFloat operator * (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); if (&x!=&y) return temp*=y; else { temp.Sqr(); return temp; } }
friend inline const TLargeFloat operator * (const TLargeFloat& x,long double y) {TLargeFloat temp(x); return temp*= y;}
friend inline const TLargeFloat operator * (long double x,const TLargeFloat& y) { return y* x; }
SelfType& operator /= (long double fValue);
SelfType& operator /= (const SelfType& Value);
friend inline const TLargeFloat operator / (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); return temp/= y; }
friend inline const TLargeFloat operator / (const TLargeFloat& x,long double y) { TLargeFloat temp(x); return temp/= y; }
friend inline const TLargeFloat operator / (long double x,const TLargeFloat& y) { TLargeFloat temp(y); temp.Rev(); return temp*= x; }
friend inline bool operator ==(const TLargeFloat& x,const TLargeFloat& y) { return (x.Compare(y)==0 ); }
friend inline bool operator < (const TLargeFloat& x,const TLargeFloat& y) { return (x.Compare(y)<0 ); }
friend inline bool operator ==(const TLargeFloat& x,long double y) { return (x== TLargeFloat(y)); }
friend inline bool operator < (const TLargeFloat& x,long double y) { return (x< TLargeFloat(y)); }
friend inline bool operator ==(long double x,const TLargeFloat& y) { return (y== x); }
friend inline bool operator < (long double x,const TLargeFloat& y) { return (y> x); }
friend inline bool operator !=(const TLargeFloat& x,const TLargeFloat& y) { return !(x== y); }
friend inline bool operator > (const TLargeFloat& x,const TLargeFloat& y) { return (y< x); }
friend inline bool operator >=(const TLargeFloat& x,const TLargeFloat& y) { return !(x< y); }
friend inline bool operator <=(const TLargeFloat& x,const TLargeFloat& y) { return !(x> y); }
friend inline bool operator !=(const TLargeFloat& x,long double y) { return !(x== y); }
friend inline bool operator > (const TLargeFloat& x,long double y) { return (y< x); }
friend inline bool operator >=(const TLargeFloat& x,long double y) { return !(x< y); }
friend inline bool operator <=(const TLargeFloat& x,long double y) { return !(x> y); }
friend inline bool operator !=(long double x,const TLargeFloat& y) { return !(x== y); }
friend inline bool operator > (long double x,const TLargeFloat& y) { return (y< x); }
friend inline bool operator >=(long double x,const TLargeFloat& y) { return !(x< y); }
friend inline bool operator <=(long double x,const TLargeFloat& y) { return !(x> y); }
friend inline const TLargeFloat abs(const TLargeFloat& x) { TLargeFloat result(x); result.Abs(); return result; }//绝对值,|x|
friend inline const TLargeFloat sqrt(const TLargeFloat& x) { TLargeFloat result(x); result.Sqrt(); return result;} //开方,x^0.5
friend inline const TLargeFloat revsqrt(const TLargeFloat& x) { TLargeFloat result(x); result.RevSqrt(); return result; }//求1/x^0.5;
friend inline const TLargeFloat sqr(const TLargeFloat& x) { TLargeFloat result(x); result.Sqr(); return result; };//平方,x^2
friend inline void swap(TLargeFloat& a,TLargeFloat& b) { a.Swap(b); }//交换值
friend inline std::ostream& operator << (std::ostream& cout, const TLargeFloat& Value) { return cout<< Value.AsString(); }
///
private :
TInt32bit m_Sign; //符号位 正:1, 负:-1, 零: 0
TExpInt m_Exponent; //保存10为底的指数
TArray m_Digits; //小数部分 排列顺序是TArray[0]为第一个小数位(em10Power个10进制位),依此类推;取值范围[0--(emBase-1)]
private :
void Canonicity();//规格化 转化值到合法格式
void fToLargeFloat(long double fValue);//内部使用 浮点数转化为 TLargeFloat,并采用默认精度
void iToLargeFloat(TMaxInt iValue);//内部使用 整数转化为 TLargeFloat,并采用默认精度
void sToLargeFloat(const std::string& strValue);//内部使用 字符串转化为 TLargeFloat
long Compare(const SelfType& Value) const;//比较两个数;(*this)>Value 返回1,小于返回-1,相等返回0
void Abs_Add(const SelfType& Value);//绝对值加 x:=|x|+|y|;
void Abs_Sub_Abs(const SelfType& Value);//绝对值减的绝对值x:=| |x|-|y| |;
public :
void Chs();//求负
void Abs();//绝对值
void MulInt(TMaxInt iValue);//乘以一个整数;
void DivInt(TMaxInt iValue);//除以一个整数;
void Rev();//求倒数
void RevSqrt();//求1/x^0.5;
inline void Sqrt() { SelfType x(*this); x.RevSqrt(); (*this)*=x; } //求x^0.5;
inline void Sqr() { (*this)*=(*this); };//平方,x^2
};
//单元测试
void LargeFloat_UnitTest();
#endif // _TLARGE_FLOAT_H__INCLUDED_
// TLargeFloat.h
/// //
// TLargeFloat.h: interface for the TLargeFloat class.
// 超高精度浮点数类TLargeFloat
// 2004.03.28 by HouSisong@GMail.com
//
// Update 2004.03.31 by HouSisong
// ......
// Update 2007.11.29-12.20 by HouSisong 重构一遍,速度加快很多,我用它计算了上亿位的PI值:)
#ifndef _TLARGE_FLOAT_H__INCLUDED_
#define _TLARGE_FLOAT_H__INCLUDED_
#include <vector>
#include <sstream>
#include <string>
#include <Exception>
#include <limits>
class TLargeFloat;//超高精度浮点数类TLargeFloat
class TLargeFloatException;// 超高精度浮点数异常类
// 改进方向:
// 1.强力优化ArrayMUL数组乘运算(当前实现了二分法和FFT算法):
// a.将实数按齐偶作为复数进行傅立叶变换的算法实现,加快乘法速度
// b.实现混合基的傅立叶变换,加快乘法速度
// c.考虑用x87的10byte浮点数实现FFT以减小误差从而增大FFT能够计算的最大位数限制
// d.用SSE2等优化快速复利叶变换,加快乘法速度
// e.或者将傅立叶变换替换为数论变换的实现(使用整数)
// 2.内部使用8位(或9位)十进制来实现,节约内存;或者2进制的底数(这样的话,输出函数就会麻烦一些了)
// 3.添加新的基本运算函数,如:指数运算power、对数运算log、三角函数sin,cos,tan等
// 注意:如果浮点数与TLargeFloat进行混合运算, 可能会产生误差(有效位数会受到浮点数影响);
// 整数 或 为可表示整数的浮点数 参与运算不会产生误差;
// 对于很大的整数或者有小数位的浮点数,建议用字符串的形式转换为超高精度浮点数(不会引入误差)
//void ArrayMUL(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize);// 数组乘, 需要优化的首要目标
//超高精度浮点数异常类 //TLargeFloat运算中出现错误的时候会抛出该类型的异常
class TLargeFloatException :public std::runtime_error
{
public :
TLargeFloatException(const char * Error_Msg) :runtime_error(Error_Msg){}
virtual ~TLargeFloatException() throw () {}
};
// TCatchIntError只是对整数类型TInt进行的一层包装
// 超高精度浮点数类的指数运算时使用
// 设计TCatchIntError是为了当整数运算超出值域的时候,抛出异常
//template<要包装的整数类型,超界时抛出的异常类型,TInt最小值,TInt最大值>
template <typename TInt,typename TException,TInt MinValue,TInt MaxValue>
class TCatchIntError
{
private :
typedef TCatchIntError<TInt,TException,MinValue,MaxValue> SelfType;
TInt m_Int;
inline SelfType& inc(const TInt& uValue)
{
if ( (uValue<0)||(uValue>MaxValue)||(MaxValue-uValue< m_Int) )
throw TException("ERROR:TCatchIntError::inc(); " );
m_Int+= uValue;
return (*this );
}
inline SelfType& dec(const TInt& uValue)
{
if ( (uValue<0)||(uValue>MaxValue)||(MinValue+uValue> m_Int) )
throw TException("ERROR:TCatchIntError::dec()" );
m_Int-= uValue;
return (*this );
}
inline SelfType& mul(const TInt& iValue)
{
if (iValue==0 )
m_Int=0 ;
else
{
TInt tmp =m_Int* iValue;
if ( (iValue<MinValue)||(iValue>MaxValue)||(tmp<MinValue)||(tmp>MaxValue)||((tmp/iValue)!= m_Int) )
throw TException("ERROR:TCatchIntError::mul(); " );
m_Int= tmp;
}
return (*this );
}
public :
inline TCatchIntError() :m_Int(0 ){ }
inline TCatchIntError(const TInt& Value) :m_Int(0) { (*this)+= Value;}
inline TCatchIntError(const SelfType& Value) :m_Int(0) { (*this)+= (Value.m_Int); }
inline const TInt& AsInt() const { return m_Int; }
inline SelfType& operator +=(const TInt& Value) //throw(TLargeFloatException)
{ if (Value<0) return dec(- Value);
else return inc(Value); }
inline SelfType& operator -=(const TInt& Value) //throw(TLargeFloatException)
{ if (Value<0) return inc(- Value);
else return dec(Value); }
inline SelfType& operator *=(const TInt& Value) //throw(TLargeFloatException)
{ return mul(Value); }
inline SelfType& operator +=(const SelfType& Value) { return (*this)+=(Value.m_Int); }//throw(TLargeFloatException)
inline SelfType& operator -=(const SelfType& Value) { return (*this)-=(Value.m_Int); }//throw(TLargeFloatException)
inline SelfType& operator *=(const SelfType& Value) { return (*this)*=(Value.m_Int); }//throw(TLargeFloatException)
};
// 指数部分使用的整数类型 填写编译器支持的较大的整数类型
//typedef __int64 TMaxInt; // type long long TMaxInt;
// const TMaxInt TMaxInt_MAX_VALUE = TMaxInt(9223372036854775807);
//const TMaxInt TMaxInt_MIN_VALUE = - TMaxInt_MAX_VALUE;
typedef long TMaxInt;
const TMaxInt TMaxInt_MAX_VALUE = 2147483647 ;
const TMaxInt TMaxInt_MIN_VALUE = - TMaxInt_MAX_VALUE;
//小数部分使用的整数类型 32bit位的整数类型
typedef long TInt32bit;
const TInt32bit TInt32bit_MAX_VALUE = 2147483647 ;
const TInt32bit TInt32bit_MIN_VALUE = - TInt32bit_MAX_VALUE;
//超高精度浮点数类
class TLargeFloat
{
public :
//一些常量和类型定义
typedef std::vector<TInt32bit> TArray;//小数位使用的数组类型
enum { em10Power =4, //数组为10000进制,
emBase =10000, //数组的一个元素对应4个十进制位
emLongDoubleDigits =std::numeric_limits<long double>::digits10,//long double的10进制有效精度
emLongDoubleMaxExponent =std::numeric_limits<long double>::max_exponent10,//long double的最大10进制指数
emLongDoubleMinExponent =std::numeric_limits<long double>::min_exponent10 };//long double的最小10进制指数
typedef TLargeFloatException TException;
typedef TCatchIntError<TMaxInt,TException,TMaxInt_MIN_VALUE,TMaxInt_MAX_VALUE> TExpInt;//指数类型
typedef TLargeFloat SelfType;
public :
class TDigits//TDigits用来设置TLargeFloat的精度;//增加这个类是为了避免TLargeFloat的构造函数的可能误用
{
private :
unsigned long m_DigitsArraySize;
public :
explicit TDigits(const long uiDigitsLength)
{ if (uiDigitsLength<=0) throw TException("ERROR:TLargeFloat::TDigits()" );
m_DigitsArraySize=(uiDigitsLength+em10Power-1)/ em10Power; }
inline const unsigned long GetDigitsArraySize() const { return m_DigitsArraySize; }
};
TLargeFloat(const SelfType& Value);
explicit TLargeFloat(const long double DefultValue);//默认浮点精度 //注意:转换可能存在小的误差
explicit TLargeFloat(const long double DefultValue,const TDigits& DigitsLength);//TDigits 十进制有效位数 //注意:转换可能存在小的误差
explicit TLargeFloat(const char* strValue);//使用字符串本身的精度
explicit TLargeFloat(const char* strValue,const TDigits& DigitsLength);
explicit TLargeFloat(const std::string& strValue);
explicit TLargeFloat(const std::string& strValue,const TDigits& DigitsLength);
long double AsFloat() const;//转化为浮点数
std::string AsString() const;//转换为字符串
void SetDigitsLength(const TDigits& DigitsLength); //重新设置10进制有效位数
inline void SetDigitsLength(const long uiDigitsLength) { SetDigitsLength(TDigits(uiDigitsLength)); }
unsigned long GetDigitsLength() const;//返回当前的10进制有效位数
void Swap(SelfType& Value);//交换值
void Zero(); //设置为0
inline void StrToLargeFloat(const std::string& strValue) { sToLargeFloat(strValue); }
inline void StrToLargeFloat(const char* strValue) { sToLargeFloat(std::string (strValue)); }
SelfType& operator = (const SelfType& Value);
SelfType& operator = (long double fValue); //注意:转换可能存在小的误差
inline const SelfType operator - () const { SelfType temp(*this); temp.Chs(); return temp; }//求负
inline const SelfType& operator + () const { return (*this); }//求正
SelfType & operator += (const SelfType& Value);
SelfType& operator -= (const SelfType& Value);
inline SelfType& operator += (long double fValue) { return (*this)+= TLargeFloat(fValue); }
inline SelfType& operator -= (long double fValue) { return (*this)-= TLargeFloat(fValue); }
friend inline const TLargeFloat operator + (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); return temp+= y; }
friend inline const TLargeFloat operator - (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); return temp-= y; }
friend inline const TLargeFloat operator + (const TLargeFloat& x,long double y) { TLargeFloat temp(x); return temp+= y; }
friend inline const TLargeFloat operator - (const TLargeFloat& x,long double y) { TLargeFloat temp(x); return temp-= y; }
friend inline const TLargeFloat operator + (long double x,const TLargeFloat& y) { return y+ x; }
friend inline const TLargeFloat operator - (long double x,const TLargeFloat& y) { return -(y- x); }
SelfType& operator *= (long double fValue);
SelfType& operator *= (const SelfType& Value);
friend inline const TLargeFloat operator * (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); if (&x!=&y) return temp*=y; else { temp.Sqr(); return temp; } }
friend inline const TLargeFloat operator * (const TLargeFloat& x,long double y) {TLargeFloat temp(x); return temp*= y;}
friend inline const TLargeFloat operator * (long double x,const TLargeFloat& y) { return y* x; }
SelfType& operator /= (long double fValue);
SelfType& operator /= (const SelfType& Value);
friend inline const TLargeFloat operator / (const TLargeFloat& x,const TLargeFloat& y) { TLargeFloat temp(x); return temp/= y; }
friend inline const TLargeFloat operator / (const TLargeFloat& x,long double y) { TLargeFloat temp(x); return temp/= y; }
friend inline const TLargeFloat operator / (long double x,const TLargeFloat& y) { TLargeFloat temp(y); temp.Rev(); return temp*= x; }
friend inline bool operator ==(const TLargeFloat& x,const TLargeFloat& y) { return (x.Compare(y)==0 ); }
friend inline bool operator < (const TLargeFloat& x,const TLargeFloat& y) { return (x.Compare(y)<0 ); }
friend inline bool operator ==(const TLargeFloat& x,long double y) { return (x== TLargeFloat(y)); }
friend inline bool operator < (const TLargeFloat& x,long double y) { return (x< TLargeFloat(y)); }
friend inline bool operator ==(long double x,const TLargeFloat& y) { return (y== x); }
friend inline bool operator < (long double x,const TLargeFloat& y) { return (y> x); }
friend inline bool operator !=(const TLargeFloat& x,const TLargeFloat& y) { return !(x== y); }
friend inline bool operator > (const TLargeFloat& x,const TLargeFloat& y) { return (y< x); }
friend inline bool operator >=(const TLargeFloat& x,const TLargeFloat& y) { return !(x< y); }
friend inline bool operator <=(const TLargeFloat& x,const TLargeFloat& y) { return !(x> y); }
friend inline bool operator !=(const TLargeFloat& x,long double y) { return !(x== y); }
friend inline bool operator > (const TLargeFloat& x,long double y) { return (y< x); }
friend inline bool operator >=(const TLargeFloat& x,long double y) { return !(x< y); }
friend inline bool operator <=(const TLargeFloat& x,long double y) { return !(x> y); }
friend inline bool operator !=(long double x,const TLargeFloat& y) { return !(x== y); }
friend inline bool operator > (long double x,const TLargeFloat& y) { return (y< x); }
friend inline bool operator >=(long double x,const TLargeFloat& y) { return !(x< y); }
friend inline bool operator <=(long double x,const TLargeFloat& y) { return !(x> y); }
friend inline const TLargeFloat abs(const TLargeFloat& x) { TLargeFloat result(x); result.Abs(); return result; }//绝对值,|x|
friend inline const TLargeFloat sqrt(const TLargeFloat& x) { TLargeFloat result(x); result.Sqrt(); return result;} //开方,x^0.5
friend inline const TLargeFloat revsqrt(const TLargeFloat& x) { TLargeFloat result(x); result.RevSqrt(); return result; }//求1/x^0.5;
friend inline const TLargeFloat sqr(const TLargeFloat& x) { TLargeFloat result(x); result.Sqr(); return result; };//平方,x^2
friend inline void swap(TLargeFloat& a,TLargeFloat& b) { a.Swap(b); }//交换值
friend inline std::ostream& operator << (std::ostream& cout, const TLargeFloat& Value) { return cout<< Value.AsString(); }
///
private :
TInt32bit m_Sign; //符号位 正:1, 负:-1, 零: 0
TExpInt m_Exponent; //保存10为底的指数
TArray m_Digits; //小数部分 排列顺序是TArray[0]为第一个小数位(em10Power个10进制位),依此类推;取值范围[0--(emBase-1)]
private :
void Canonicity();//规格化 转化值到合法格式
void fToLargeFloat(long double fValue);//内部使用 浮点数转化为 TLargeFloat,并采用默认精度
void iToLargeFloat(TMaxInt iValue);//内部使用 整数转化为 TLargeFloat,并采用默认精度
void sToLargeFloat(const std::string& strValue);//内部使用 字符串转化为 TLargeFloat
long Compare(const SelfType& Value) const;//比较两个数;(*this)>Value 返回1,小于返回-1,相等返回0
void Abs_Add(const SelfType& Value);//绝对值加 x:=|x|+|y|;
void Abs_Sub_Abs(const SelfType& Value);//绝对值减的绝对值x:=| |x|-|y| |;
public :
void Chs();//求负
void Abs();//绝对值
void MulInt(TMaxInt iValue);//乘以一个整数;
void DivInt(TMaxInt iValue);//除以一个整数;
void Rev();//求倒数
void RevSqrt();//求1/x^0.5;
inline void Sqrt() { SelfType x(*this); x.RevSqrt(); (*this)*=x; } //求x^0.5;
inline void Sqr() { (*this)*=(*this); };//平方,x^2
};
//单元测试
void LargeFloat_UnitTest();
#endif // _TLARGE_FLOAT_H__INCLUDED_
// TLargeFloat.h
/// //
类的实现文件:TLargeFloat.cpp
/////
// TLargeFloat.cpp: implementation of the TLargeFloat class.
// 超高精度浮点数类TLargeFloat
//
#include "TLargeFloat.h"
#include <algorithm>
//#include "assert.h"
#include <math.h>
// #define MyDebugAssert(b) { if (!(b)) __asm{ int 3 } }
//用以控制运算精度的工具
class TDigitsLengthCtrl
{
private :
std::vector<TLargeFloat*> m_list;
public :
inline void add_to_ctrl(TLargeFloat* var) { m_list.push_back(var); }
void SetDigitsLength(const long uiDigitsLength)
{
long size= m_list.size();
for (long i=0;i<size;++ i)
m_list[i]-> SetDigitsLength(uiDigitsLength);
}
};
//自动精度控制
class TDigitsLengthAutoCtrl:public TDigitsLengthCtrl
{
private :
std::vector<long> m_DigitsLengthList;
long step;
public :
TDigitsLengthAutoCtrl(long DigitsMul,long DigitsLength0,long MaxDigitsLength)//(收敛系数,初始精度,最终需要精度)
{
// MyDebugAssert(DigitsLength0>0);
//得到最佳的精度梯度
long curDigitsLength= MaxDigitsLength;
while (curDigitsLength> DigitsLength0)
{
m_DigitsLengthList.push_back(curDigitsLength);
if ((DigitsLength0<=1)&&(curDigitsLength==1)) break ;
curDigitsLength=(curDigitsLength+DigitsMul-1)/ DigitsMul;
}
step=get_runcount()-1 ;
}
inline long get_runcount() { return m_DigitsLengthList.size(); }
inline void SetNextDigits()
{
//MyDebugAssert(step>=0);
long DigitsLength= m_DigitsLengthList[step];
if (step>0 )
DigitsLength+=4 ;
SetDigitsLength(DigitsLength);
-- step;
if (step<0) step=0 ;
}
};
/
void TLargeFloat_CtrlExponent(TLargeFloat::TArray& v,TMaxInt iMoveRightCount)
{
//iMoveCountBig 有可能存不下 但现在的体系下因右移超过值域比较难
long iMoveCountBig=(long)(iMoveRightCount/ TLargeFloat::em10Power);
long iMoveCountSmall=(long)(iMoveRightCount% TLargeFloat::em10Power);
//大的右移
if (iMoveCountBig>0 )
{
for (long i=v.size()-1;i>=iMoveCountBig;-- i)
v[i]=v[i- iMoveCountBig];
for (long j=0;j<iMoveCountBig;++ j)
v[j]=0 ;
}
//小的右移
if (iMoveCountSmall>0 )
{
TInt32bit iDiv=1 ;
for (long j=0;j<iMoveCountSmall;++j) iDiv*=10 ;
long v_size= v.size();
for (long i=iMoveCountBig;i<v_size-1;++ i)
{
v[i+1]+=(v[i]%iDiv)* TLargeFloat::emBase;
v[i]/= iDiv;
}
if (v_size>=1 )
v[v_size-1]/= iDiv;
}
}
void TLargeFloat_ArrayAddTestLast(TInt32bit* x,long xsize)
{
for (long i=xsize-1;i>0;-- i)
{
if (x[i]>=TLargeFloat::emBase)//进位
{
++x[i-1 ];
x[i]-= TLargeFloat::emBase;
}
else
break ;
}
}
void TLargeFloat_ArrayAdd(TInt32bit* result,long rsize,const TInt32bit* y,long ysize)
{
// MyDebugAssert(rsize>=ysize);
//MyDebugAssert(ysize>0);
TInt32bit* ri=&result[rsize- ysize];
long i;
for (i=ysize-1;i>0;-- i)
{
TInt32bit r=ri[i]+ y[i];
if (r>=TLargeFloat::emBase)//进位
{
++ri[i-1 ];
r-= TLargeFloat::emBase;
}
ri[i]= r;
}
ri[0]+=y[0 ];
TLargeFloat_ArrayAddTestLast(result,rsize-ysize+1 );
}
void TLargeFloat_ArraySub(TInt32bit* result,long rsize,const TInt32bit* y,long ysize)
{
// MyDebugAssert(rsize>=ysize);
//MyDebugAssert(ysize>0);
TInt32bit* ri=&result[rsize- ysize];
long i;
for (i=ysize-1;i>0;-- i)
{
TInt32bit r=ri[i]- y[i];
if (r<0)//借位
{
--ri[i-1 ];
r+= TLargeFloat::emBase;
}
ri[i]= r;
}
ri[0]-=y[0 ];
for (i=rsize-ysize;i>0;-- i)
{
if (result[i]<0)//借位
{
--result[i-1 ];
result[i]+= TLargeFloat::emBase;
}
else
break ;
}
}
TInt32bit _inti_csMaxMuliValue()
{
double rb=1; double mb=1 ;
for (long i=0;i<100/TLargeFloat::em10Power;++ i)
{
mb*=(1.0/ TLargeFloat::emBase);
rb+= mb;
}
return (TInt32bit)( TInt32bit_MAX_VALUE*(1.0/(TLargeFloat::emBase-1))/rb ) -1 ;
}
//不超界所允许的乘数值M满足: (emBase-1)*M + (emBase-1)*M/B + (emBase-1)*M/B^2 + (emBase-1)*M/B^3 ... <=TInt32bit_MAX_VALUE
static const TInt32bit csMaxMuliValue= _inti_csMaxMuliValue();
static const TInt32bit csMaxMulAddValue = csMaxMuliValue - (TLargeFloat::emBase-1 );
void TLargeFloat_ArrayMUL_ExE(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize)
{
//N*N复杂度的简单乘法实现
for (long k=0;k<rminsize;++k) result[k]=0 ;
while ((ysize>0)&&(y[0]==0)) { --ysize; ++y; ++result; -- rminsize;}
//while ((xsize>0)&&(x[0]==0)) { --xsize; ++x; ++result; --rminsize;}
while ((ysize>0)&&(y[ysize-1]==0)) { -- ysize; }
//while ((xsize>0)&&(x[xsize-1]==0)) { --xsize; }
long add_sum=0 ;
for (long i=0;i<xsize;++ i)
{
long xi= x[i];
if (xi>0 )
{
TInt32bit* resulti=&result[i+1 ];
long y_limit=std::min(rminsize-1- i,ysize);
for (long j=0;j<y_limit;++ j)
{
resulti[j]+=(xi* y[j]);
}
add_sum+= xi;
if (add_sum> csMaxMulAddValue)
{
for (long k=i+y_limit;k>0;-- k)
{
TInt32bit v= result[k];
if (v>= TLargeFloat::emBase)
{
result[k-1]+=v/ TLargeFloat::emBase;
result[k]= v% TLargeFloat::emBase;
}
}
add_sum=0 ;
}
}
}
if (add_sum>0 )
{
for (long k=rminsize-1;k>0;-- k)
{
TInt32bit v= result[k];
if (v>= TLargeFloat::emBase)
{
result[k-1]+=v/ TLargeFloat::emBase;
result[k]= v% TLargeFloat::emBase;
}
}
}
}
//数组乘法 核心
void ArrayMUL(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize);
void ArrayMUL_Dichotomy(TInt32bit* result,long rminsize,const TInt32bit* x,const TInt32bit* y,long MulSize)
{
// 二分法的乘法实现
// x*y=(a*E+b)*(c*E+d)=(E*E-E)*ac + E*(a+b)*(c+d) -(E-1)*bd
// temp_a_add_b=a+b;
// temp_c_add_d=c+d;
// result=E*temp_a_add_b*temp_c_add_d;
// temp_ac=a*c;
// result+=E*E*temp_ac;
// result-=E*temp_ac;
// temp_bd=b*d;
// result+=temp_bd;
// result-=E*temp_bd;
//
long i;
const long E=((MulSize+1)>>1 );
//if (tmpData+2*(E+1)>end_tmpData) __asm int 3
const long acSize=MulSize- E;
const long acErrorSize=E- acSize;
const TInt32bit* a= x;
const TInt32bit* b=& x[acSize];
const TInt32bit* c= y;
const TInt32bit* d=& y[acSize];
TLargeFloat::TArray _tmpData((E+1)*2 );
TInt32bit* tmpData=&_tmpData[0 ];
TInt32bit* temp_a_add_b=&tmpData[0 ];
TInt32bit* temp_c_add_d=&tmpData[(E+1 )];
temp_a_add_b[0]=0 ;
for (i=0;i<E;++i) temp_a_add_b[i+1]= b[i];
TLargeFloat_ArrayAdd(temp_a_add_b,1+E,a,E- acErrorSize);
temp_c_add_d[0]=0 ;
for (i=0;i<E;++i) temp_c_add_d[i+1]= d[i];
TLargeFloat_ArrayAdd(temp_c_add_d,1+E,c,E- acErrorSize);
const long abcdPos=(2*MulSize-E-2*(E+1 ));
for (i=0;i<abcdPos;++i) result[i]=0 ;
ArrayMUL(&result[abcdPos],std::min(rminsize-abcdPos,2*(E+1)),temp_a_add_b,E+1,temp_c_add_d,E+1 );
for (i=abcdPos+2*(E+1);i<rminsize;++i) result[i]=0 ;
TInt32bit* temp_ac=&tmpData[0 ];
const long acminsize=std::min(rminsize,acSize*2 );
ArrayMUL(temp_ac,acminsize,a,acSize,c,acSize);
TLargeFloat_ArrayAdd(result,acminsize,temp_ac,acminsize);
long sub_ac_size=acSize*2 ;
if (E+sub_ac_size>rminsize) sub_ac_size=rminsize- E;
TLargeFloat_ArraySub(result,E+ sub_ac_size,temp_ac,sub_ac_size);
const long add_bdPos=2*MulSize-2* E;
long sub_bd_size=2* E;
const long sub_bdPos=add_bdPos- E;
if (sub_bdPos+sub_bd_size>rminsize) sub_bd_size=rminsize- sub_bdPos;
if (sub_bd_size>0 )
{
TInt32bit* temp_bd=&tmpData[0 ];
ArrayMUL(temp_bd,sub_bd_size,b,E,d,E);
long add_bd_size=2* E;
if (add_bdPos+add_bd_size>rminsize) add_bd_size=rminsize- add_bdPos;
if (add_bd_size>0 )
TLargeFloat_ArrayAdd(result,add_bdPos+ add_bd_size,temp_bd,add_bd_size);
TLargeFloat_ArraySub(result,sub_bdPos+ sub_bd_size,temp_bd,sub_bd_size);
}
}
void ArrayMUL_DichotomyPart(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize)
{
//二分法的辅助函数
///
//x*y=(a*E+b)*y=a*y*E+b*y;
if (xsize== ysize)
{
ArrayMUL_Dichotomy(result,rminsize,x,y,ysize);
return ;
}
if (xsize< ysize)
{
std::swap(xsize,ysize);
std::swap(x,y);
}
const long E= ysize;
const long asize=xsize- E;
const TInt32bit* a=&x[0 ];
const TInt32bit* b=& x[asize];
ArrayMUL(result,rminsize,a,asize,y,ysize);
for (long i=asize+ysize;i<rminsize;++i) result[i]=0 ;
const long byPos= asize;
if (byPos< rminsize)
{
const long byminsize=rminsize- byPos;
TLargeFloat::TArray tmpData(byminsize);
TInt32bit* tmp_by=&tmpData[0 ];
ArrayMUL_Dichotomy(tmp_by,byminsize,b,y,E);
TLargeFloat_ArrayAdd(result,rminsize,tmp_by,byminsize);
}
}
/
const long csTMaxInt_Digits=(long)(log10((long double)TMaxInt_MAX_VALUE)+1 );
TLargeFloat::TLargeFloat(const SelfType& Value)
:m_Digits(Value.m_Digits)
{
m_Exponent= Value.m_Exponent;
m_Sign= Value.m_Sign;
}
TLargeFloat::TLargeFloat(const long double DefultValue)
:m_Digits(TDigits(emLongDoubleDigits+1).GetDigitsArraySize(),0 )
{
fToLargeFloat(DefultValue);
}
TLargeFloat::TLargeFloat(const long double DefultValue,const TDigits& DigitsLength)
:m_Digits(DigitsLength.GetDigitsArraySize(),0 )
{
fToLargeFloat(DefultValue);
}
TLargeFloat::TLargeFloat(const char* strValue)
:m_Digits(TDigits(csTMaxInt_Digits).GetDigitsArraySize(),0 )
{
sToLargeFloat(std::string (strValue));
}
TLargeFloat::TLargeFloat(const char* strValue,const TDigits& DigitsLength)
:m_Digits(DigitsLength.GetDigitsArraySize(),0 )
{
sToLargeFloat(std::string (strValue));
}
TLargeFloat::TLargeFloat(const std::string& strValue)
:m_Digits(TDigits(csTMaxInt_Digits).GetDigitsArraySize(),0 )
{
sToLargeFloat(strValue);
}
TLargeFloat::TLargeFloat(const std::string& strValue,const TDigits& DigitsLength)
:m_Digits(DigitsLength.GetDigitsArraySize(),0 )
{
sToLargeFloat(strValue);
}
void TLargeFloat::Zero()
{
if (m_Sign==0) return ;
m_Sign=0 ;
m_Exponent=0 ;
long old_size= m_Digits.size();
for (long i=0;i<old_size;++ i)
m_Digits[i]=0 ;
}
void TLargeFloat::Canonicity()
{
// 规格化 小数部分
// 规格化前允许:m_Digits[0]>=emBase 也就是小数部分的值大于等于1.0;
// 规格化前允许:m_Digits[]前面有多个0值 也就是小数部分的值小于0.1;
//规格化后的数满足的条件:小数部分的值 小于1.0,大于等于0.1;
if (m_Sign==0 )
{
return ;
}
long old_size= m_Digits.size();
if (old_size<=0) return; //不可能发生:)
if ( (m_Digits[0]<emBase)&&(m_Digits[0]>=(emBase/10)) ) return ;
//处理右移
while (m_Digits[0]>=emBase)//是否需要右移1
{
m_Exponent+= em10Power;
for (long i=old_size-1;i>=2;-- i)
m_Digits[i]=m_Digits[i-1 ];
if (old_size>=2) m_Digits[1]=m_Digits[0] % emBase;
m_Digits[0]/= emBase;
}
// 考虑左移
//大的左移
long iMoveCountBig= old_size;
for (long i=0;i<old_size;++ i)
{
if (m_Digits[i]!=0 )
{
iMoveCountBig= i;
break ;
}
}
if (iMoveCountBig== old_size)
{
//as Zero();
m_Sign=0 ;
m_Exponent=0 ;
return ;
}
if (iMoveCountBig>0 )
{
m_Exponent-=(iMoveCountBig* em10Power);
for (long j=0;j<old_size-iMoveCountBig;++ j)
m_Digits[j]=m_Digits[j+ iMoveCountBig];
for (long k=old_size-iMoveCountBig;k<old_size;++ k)
m_Digits[k]=0 ;
}
//小的左移
TInt32bit iMoveMul=1 ;
long iMoveCountSmall=0 ;
while (iMoveMul*m_Digits[0]<(emBase/10 ))
{
iMoveMul*=10 ;
++ iMoveCountSmall;
}
if (iMoveCountSmall>0 )
{
m_Exponent-= iMoveCountSmall;
for (long i=old_size-1;i>=0;-- i)
m_Digits[i]*= iMoveMul;
for (long j=old_size-1;j>0;-- j)
{
TInt32bit value= m_Digits[j];
m_Digits[j]=value% emBase;
m_Digits[j-1]+=value/ emBase;
}
}
}
void TLargeFloat::iToLargeFloat(TMaxInt iValue)
{
Zero();
long new_size= TDigits(csTMaxInt_Digits).GetDigitsArraySize();
if ((long)m_Digits.size()< new_size)
m_Digits.resize(new_size,0 );
if (iValue==0 )
return ;
else if (iValue>0 )
m_Sign=1 ;
else
{
m_Sign =-1 ;
iValue=- iValue;
}
//无误差转换
TMaxInt tmp_iValue= iValue;
long n=0 ;
for (;tmp_iValue!=0;++ n)
tmp_iValue/= emBase;
m_Exponent=n* em10Power;
for (long i=0;i<n;++ i)
{
m_Digits[n-1-i]=(TInt32bit)(iValue% emBase);
iValue/= emBase;
}
Canonicity();
}
void TLargeFloat::fToLargeFloat(long double fValue)
{
TMaxInt iValue= (TMaxInt)fValue;
if (iValue== fValue)
{
iToLargeFloat(iValue);
return ;
}
Zero();
long new_size=TDigits(emLongDoubleDigits+1 ).GetDigitsArraySize();
if ((long)m_Digits.size()< new_size)
m_Digits.resize(new_size,0 );
if (fValue==0 )
return ;
else if (fValue>0 )
m_Sign=1 ;
else
{
m_Sign =-1 ;
fValue=- fValue;
}
m_Exponent=(long )floor(log10(fValue));
fValue/=pow(10.0,(long )m_Exponent.AsInt());
long size= m_Digits.size();
for (long i=0;i<size;++i)//得到小数位
{
if (fValue<=0) break ;
fValue*= emBase;
TInt32bit iValue= (TInt32bit)floor(fValue);
fValue-= iValue;
m_Digits[i]= iValue;
}
Canonicity();
}
void TLargeFloat::Swap(SelfType& Value)
{
if (this==&Value) return ;
m_Digits.swap(Value.m_Digits);
std::swap(m_Sign,Value.m_Sign);
std::swap(m_Exponent,Value.m_Exponent);
}
void TLargeFloat::Chs()
{
m_Sign*=(-1 );
}
void TLargeFloat::Abs()
{
if (m_Sign!=0) m_Sign=1 ;
}
unsigned long TLargeFloat::GetDigitsLength() const
{
return m_Digits.size()* em10Power;
}
void TLargeFloat::SetDigitsLength(const TDigits& DigitsLength)
{
m_Digits.resize(DigitsLength.GetDigitsArraySize(),0 );
}
TLargeFloat::SelfType& TLargeFloat::operator = (const SelfType& Value)
{
if (this==&Value) return *this ;
m_Digits= Value.m_Digits;
m_Sign= Value.m_Sign;
m_Exponent= Value.m_Exponent;
return *this ;
}
TLargeFloat::SelfType& TLargeFloat::operator = (long double fValue)
{
fToLargeFloat(fValue);
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*pow((long double)10.0,(long double )m_Exponent.AsInt());
long double r=1 ;
long double Sum=0 ;
long old_size= m_Digits.size();
for (long i=0;i<old_size;++i)//得到小数位
{
r/=emBase;//r*=(1.0/emBase);
if (r==0) break ;
Sum+=(m_Digits[i]* r);
}
return result* Sum;
}
std::string TLargeFloat::AsString() const
{
if (m_Sign==0 )
return "0" ;
//计算需要的字符串空间大小
long str_length=2+m_Digits.size()* em10Power;
if (m_Sign<0) ++str_length; //负号
TMaxInt EpValue = m_Exponent.AsInt();
long UEP_StrLength=0 ;
if (EpValue!=0 )
{
++ str_length;
if (EpValue<0 )
{
EpValue=- EpValue;
++ str_length;
}
UEP_StrLength=0 ;
while (EpValue>0 )
{
EpValue/=10 ;
++ UEP_StrLength;
}
str_length+= UEP_StrLength;
}
std::string result(str_length,' ' );
std::string::value_type* pStr=&result[0 ];
//输出字符串
if (m_Sign<0) { *pStr='-'; ++ pStr; }
*pStr='0'; ++pStr; *pStr='.'; ++ pStr;
long dgsize= m_Digits.size();
for (long i=0;i<dgsize;++ i)
{
TInt32bit Value= m_Digits[i];
for (long d=0;d<em10Power;++ d)
{
pStr[em10Power-1-d]=(char)('0'+(Value%10 ));
Value/=10 ;
}
pStr+= em10Power;
}
EpValue= m_Exponent.AsInt();
if (EpValue!=0 )
{
*pStr='e'; ++ pStr;
if (EpValue<0 )
{
EpValue=- EpValue;
*pStr='-'; ++ pStr;
}
for (long i=0;i<UEP_StrLength;++ i)
{
pStr[UEP_StrLength-1-i]=(char)('0'+(EpValue%10 ));
EpValue/=10 ;
}
pStr+= UEP_StrLength;
}
return result;
}
template<class PChar>
PChar sToLargeFloat_GetCharIntEnd(PChar int_begin,PChar str_end)
{
long int_count=0 ;
for (PChar i=int_begin;i<str_end;++ i)
{
if ( ('0'<=(*i)) && ((*i)<='9' ) )
++ int_count;
else
break ;
}
return & int_begin[int_count];
}
inline void sToLargeFloat_setAChar(TLargeFloat::TArray& Digits,long set_index,char aChar)
{
unsigned long Value=aChar-'0' ;
long e10Power_count=TLargeFloat::em10Power-1-(set_index% TLargeFloat::em10Power);
for (long i=0;i<e10Power_count;++ i)
Value*=10 ;
Digits[set_index/TLargeFloat::em10Power]+= Value;
}
void TLargeFloat::sToLargeFloat(const std::string& strValue)
{
if (strValue.size()<=0 )
{
this-> Zero();
return ;
}
typedef const std::string::value_type* PChar;
PChar pstr_begin= strValue.c_str();
PChar pstr_end=& pstr_begin[strValue.size()];
//str as: [+|-][0..9][.][0..9][E|e][+|-][0..9]
bool is_have_sign=false ;
long sign=1 ;
bool is_have_int=false ;
PChar int_begin=0; PChar int_end=0 ;
bool is_have_dot=false ;
bool is_have_digits=false ;
PChar digits_begin=0; PChar digits_end=0 ;
bool is_have_ep=false ;
bool is_have_ep_sign=false ;
long ep_sign=1 ;
bool is_have_ep_int=false ;
PChar ep_int_begin=0; PChar ep_int_end=0 ;
//处理正负号
if ((*pstr_begin)=='-' )
{
sign = -1 ;
is_have_sign=true ;
++ pstr_begin;
}
else if ((*pstr_begin)=='+' )
{
is_have_sign=true ;
++ pstr_begin;
}
//处理前面的整数部分
int_begin= pstr_begin;
int_end= sToLargeFloat_GetCharIntEnd(int_begin,pstr_end);
is_have_int=(int_begin!= int_end);
if ((int_end-int_begin>=2)&&((*int_begin)=='0')) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 0"); //'0?'数字表示错误
pstr_begin= int_end;
if (((*pstr_begin)!='.')&&(!is_have_int)) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 1"); // 没有任何数字
//处理小数部分
if ((*pstr_begin)=='.' )
{
is_have_dot=true ;
++ pstr_begin;
digits_begin= pstr_begin;
digits_end= sToLargeFloat_GetCharIntEnd(digits_begin,pstr_end);
is_have_digits=(digits_begin!= digits_end);
if ((!is_have_digits)&&(!is_have_int)) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 2"); //没有任何数字
pstr_begin= digits_end;
}
//处理指数部分
if ( ((*pstr_begin)=='e')||((*pstr_begin)=='E' ) )
{
is_have_ep=true ;
++ pstr_begin;
//处理指数的正负号
if ((*pstr_begin)=='-' )
{
ep_sign = -1 ;
is_have_ep_sign=true ;
++ pstr_begin;
}
else if((*pstr_begin)=='+' )
{
is_have_ep_sign=true ;
++ pstr_begin;
}
//处理指数中的整数
ep_int_begin= pstr_begin;
ep_int_end= sToLargeFloat_GetCharIntEnd(ep_int_begin,pstr_end);
is_have_ep_int=(ep_int_begin!= ep_int_end);
if ((ep_int_end-ep_int_begin>=2)&&((*ep_int_begin)=='0')) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 3"); //'0?'数字表示错误
pstr_begin= ep_int_end;
if (!is_have_ep_int) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 4"); //指数没有数字
}
if (pstr_begin!=pstr_end) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 5"); //未预料的字符
//
//实际的类型转换
this-> Zero();
this->m_Sign= sign;
this->m_Exponent=(int_end- int_begin);
long need_digits_count=(int_end-int_begin)+(digits_end- digits_begin);
if ((long)this->GetDigitsLength()< need_digits_count)
this-> SetDigitsLength(need_digits_count);
long set_index=0 ;
PChar set_begin= int_begin;
for (;set_begin<int_end;++set_begin,++ set_index)
sToLargeFloat_setAChar(this->m_Digits,set_index,* set_begin);
set_begin= digits_begin;
for (;set_begin<digits_end;++set_begin,++ set_index)
sToLargeFloat_setAChar(this->m_Digits,set_index,* set_begin);
if (is_have_ep)
{
TExpInt ep=0 ;
for (PChar set_begin=ep_int_begin;set_begin<ep_int_end;++ set_begin)
{
ep*=10 ;
ep+=((*set_begin)-'0' );
}
ep*= ep_sign;
this->m_Exponent+= ep;
}
Canonicity();
}
long TLargeFloat::Compare(const SelfType& Value) const
{
if (this==&Value) return 0 ;
// (*this)>Value 返回1,小于返回-1,相等返回0
//比较符号
if (m_Sign> Value.m_Sign)
return 1 ;
else if(m_Sign< Value.m_Sign)
return -1 ;
else //m_Sign==Value.m_Sign
{
if(m_Sign==0 )
return 0 ;
}
// m_Sign==Value.m_Sign
//比较指数
if (m_Exponent.AsInt()> Value.m_Exponent.AsInt())
return m_Sign;
else if (m_Exponent.AsInt()< Value.m_Exponent.AsInt())
return - m_Sign;
else//(m_Exponent==Value.m_Exponent)
{
long sizeS= m_Digits.size();
long sizeV= Value.m_Digits.size();
long min_size= std::min(sizeS,sizeV);
for (long i=0;i<min_size;++ i)
{
if (m_Digits[i]!= Value.m_Digits[i])
{
if (m_Digits[i]> Value.m_Digits[i])
return m_Sign;
else //if (m_Digits[i]<Value.m_Digits[i])
return - m_Sign;
}
}
//继续比较 处理尾部
if (sizeS> sizeV)
{
for (long i=sizeV;i<sizeS;++ i)
{
if (m_Digits[i]>0 )
return m_Sign;;
}
}
else if (sizeS< sizeV)
{
for (long i=sizeS;i<sizeV;++ i)
{
if (Value.m_Digits[i]>0 )
return - m_Sign;
}
}
//sizeS==sizeV
return 0 ;
}
}
//
//+ -
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)
{
TInt32bit oldSign= m_Sign;
Abs_Add(Value);
m_Sign= oldSign;
return *this ;
}
else
return *this-=(- Value);
}
TLargeFloat::SelfType& TLargeFloat::operator -= (const SelfType& Value)
{
if (Value.m_Sign==0 )
return (*this );
else if (m_Sign==0 )
{
(*this)=- Value;
return (*this );
}
else if (m_Sign== Value.m_Sign)
{
long comResult=this-> Compare(Value);
if (comResult==0 )
{
this-> Zero();
}
else
{
Abs_Sub_Abs(Value);
m_Sign = comResult;
}
return *this ;
}
else
return *this+=(- Value);
}
void TLargeFloat::Abs_Add(const SelfType& Value)//绝对值加法
{
this-> Abs();
SelfType Right(Value);
Right.Abs();
//精度一致
if (m_Digits.size()< Right.m_Digits.size())
m_Digits.resize(Right.m_Digits.size(),0 );
else if (m_Digits.size()> Right.m_Digits.size())
Right.m_Digits.resize(m_Digits.size(),0 );
//被加数指数较大就可以了
if (m_Exponent.AsInt()< Right.m_Exponent.AsInt())
this-> Swap(Right);
long size= m_Digits.size();
TMaxInt iMoveRightCount=m_Exponent.AsInt()- Right.m_Exponent.AsInt();
if (iMoveRightCount>=size*(TMaxInt)TLargeFloat::em10Power) return ;
TLargeFloat_CtrlExponent(Right.m_Digits,iMoveRightCount);//对齐小数点
TLargeFloat_ArrayAdd( &m_Digits[0],size,&Right.m_Digits[0 ],size);
if (m_Digits[0]>= emBase)
Canonicity();
}
void TLargeFloat::Abs_Sub_Abs(const SelfType& Value)//绝对值减法
{
this-> Abs();
SelfType Right(Value);
Right.Abs();
long comResult=this-> Compare(Right);
if (comResult==0 )
{
this-> Zero();
return ;
}
else if (comResult<0 )
this-> Swap(Right);
//精度一致
if (m_Digits.size()< Right.m_Digits.size())
m_Digits.resize(Right.m_Digits.size(),0 );
else if (m_Digits.size()> Right.m_Digits.size())
Right.m_Digits.resize(m_Digits.size(),0 );
long size= m_Digits.size();
TMaxInt iMoveRightCount=m_Exponent.AsInt()- Right.m_Exponent.AsInt();
if (iMoveRightCount>=size*(TMaxInt)TLargeFloat::em10Power) return ;
TLargeFloat_CtrlExponent(Right.m_Digits,iMoveRightCount); //对齐小数点
TLargeFloat_ArraySub( &m_Digits[0],size,&Right.m_Digits[0 ],size);
if (m_Digits[0]*10< emBase)
Canonicity();
}
/
// /
//最大的32bit整数除数M满足: (emBase-1)+(M-1)*emBase<=TInt32bit_MAX_VALUE
const TInt32bit csMaxDiviValue=TInt32bit_MAX_VALUE/TLargeFloat::emBase -1 ;
//最大的整数除数M满足: (emBase-1)+(M-1)*emBase<=TMaxInt_MAX_VALUE
const TMaxInt csMaxDiviValueBig=TMaxInt_MAX_VALUE/TLargeFloat::emBase -1 ;
void TLargeFloat::DivInt(TMaxInt iValue)//除以一个整数
{
if (iValue==0 )
throw TException("ERROR:TLargeFloat::DivInt()" );
else if (iValue<0 )
{
iValue=- iValue;
this-> Chs();
//continue
}
if (iValue==1) return ;
if (this->m_Sign==0) return ;
if (iValue> csMaxDiviValueBig)
{
TLargeFloat y(0.0 );
y.iToLargeFloat(iValue);
(*this)/= y;
return ;
}
if (iValue<= csMaxDiviValue)
{
TInt32bit iDiv= (TInt32bit)iValue;
long size= m_Digits.size();
for (long i=0;i<size-1;++ i)
{
m_Digits[i+1]+=(m_Digits[i]%iDiv)* emBase;
m_Digits[i]/= iDiv;
}
if (size>=1 )
m_Digits[size-1]/= iDiv;
}
else
{
TMaxInt iDiv= iValue;
long size= m_Digits.size();
TMaxInt cur_value=m_Digits[0 ];
for (long i=0;i<size-1;++ i)
{
m_Digits[i]=(TInt32bit)(cur_value/ iDiv);
cur_value=m_Digits[i+1]+(cur_value%iDiv)* emBase;
}
if (size>=1 )
m_Digits[size-1]=(TInt32bit)(cur_value/ iDiv);
}
Canonicity();
}
TLargeFloat::SelfType& TLargeFloat::operator /= (long double fValue)
{
TMaxInt iValue= (TMaxInt)fValue;
if (iValue== fValue)
{
DivInt(iValue);
return *this ;
}
else
return (*this)/= TLargeFloat(fValue);
}
TLargeFloat::SelfType& TLargeFloat::operator /= (const SelfType& Value)
{
SelfType x(Value);
x.Rev();//x=1/x;
return (*this)*= x;
}
void TLargeFloat::Rev()//求倒数
{
// 求1/a,
// 则有a=1/x; y=a-1/x;
// 求导得y'=1/x^2;
// 代入牛顿方程 x(n+1)=x(n)-y(x(n))/y'(x(n));
// 有迭代式 x_next=(2-a*x)*x; // 可证明:该公式为2阶收敛公式
// 证明:令x=1/a+dx;
// 则有x_next-1/a=(2-a*(1/a+dx))*(1/a+dx)-1/a
// =(-a)*dx^2
// 证毕.
if (this->m_Sign==0) throw TException("ERROR:TLargeFloat::Rev()" );
TExpInt oldExponent= m_Exponent;
SelfType a(*this );
a.m_Exponent=0 ;
SelfType x(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
x=1.0/a.AsFloat();//初始迭代值
TDigitsLengthAutoCtrl dlCtrl( 2,emLongDoubleDigits-1,(a.m_Digits.size()* TLargeFloat::em10Power));
SelfType ta(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
SelfType temp(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
dlCtrl.add_to_ctrl(& ta);
dlCtrl.add_to_ctrl(& x);
dlCtrl.add_to_ctrl(& temp);
for (long i=0;i<dlCtrl.get_runcount();++ i)
{
ta= a;
dlCtrl.SetNextDigits();
//x=x*2-x*x*ta;
temp= x;
temp*= temp;
temp*= ta;
x*=2 ;
x-= temp;
}
x.m_Exponent-= oldExponent;
this-> Swap(x);
}
/////
//
void TLargeFloat::RevSqrt() //
{
// 求1/a^0.5,
// 则有a=1/x^2; y=a-1/x^2;
// 求导得y'=2/x^3;
// 代入牛顿方程 x(n+1)=x(n)-y(x(n))/y'(x(n));
// 有迭代式 x_next=(3-a*x*x)*x/2; // 可证明:该公式为2阶收敛公式
// 证明:令x=1/a^0.5+dx;
// 则有x_next-1/a^0.5=(3-a*(1/a^0.5+dx)*(1/a^0.5+dx))*(1/a^0.5+dx)/2 - 1/a^0.5
// =-(1.5/a^0.5)*dx^2-0.5*a*dx^3;
// 证毕.
if (this->m_Sign<0) throw TException("ERROR:TLargeFloat::RevSqrt()" );
if (this->m_Sign==0) return ;
SelfType a(*this );
TMaxInt sqrExponent=a.m_Exponent.AsInt()/2 ;
a.m_Exponent-=(sqrExponent*2 );
SelfType x(0.0 ,TDigits(a.GetDigitsLength()));
x=1.0/sqrt(a.AsFloat());//初始迭代值
TDigitsLengthAutoCtrl dlCtrl( 2,emLongDoubleDigits-1,(a.m_Digits.size()* TLargeFloat::em10Power));
SelfType ta(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
SelfType temp(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
dlCtrl.add_to_ctrl(& ta);
dlCtrl.add_to_ctrl(& x);
dlCtrl.add_to_ctrl(& temp);
for (long i=0;i<dlCtrl.get_runcount();++ i)
{
ta= a;
dlCtrl.SetNextDigits();
//x=(3-x*x*ta)*x/2;
temp= x;
temp*= temp;
temp*= ta;
temp.Chs();
temp+=3 ;
x*= temp;
x/=2 ;
}
x.m_Exponent-= sqrExponent;
this-> Swap(x);
}
////
//*
void TLargeFloat::MulInt(TMaxInt iValue)
{
if (this->m_Sign==0) return ;
if (iValue==0 )
{
this-> Zero();
return ;
}
else if (iValue<0 )
{
iValue=- iValue;
this-> Chs();
//continue
}
if (iValue> csMaxMuliValue)
{
TLargeFloat y(0.0 );
y.iToLargeFloat(iValue);
(*this)*= y;
return ;
}
//乘以一个整数
TInt32bit Value= (TInt32bit)iValue;
long size= m_Digits.size();
for (long i=size-1;i>=0;-- i)
{
m_Digits[i]*= Value;
}
for (long j=size-1;j>=1;-- j)
{
if (m_Digits[j]>= emBase)
{
m_Digits[j-1]+=m_Digits[j]/ emBase;
m_Digits[j]%= emBase;
}
}
Canonicity();
}
TLargeFloat::SelfType& TLargeFloat::operator *= (long double fValue)
{
TMaxInt iValue= (TMaxInt)fValue;
if (iValue== fValue)
{
MulInt(iValue);
return *this ;
}
else
{
TLargeFloat temp(fValue);
return (*this)*= temp;
}
}
inline void getBestMulSize(const TInt32bit*& x,long& xsize,const TInt32bit*& y,long& ysize)
{
long bxsize= xsize;
long bysize= ysize;
long i;
for (i=xsize-1;i>=0;-- i)
{
if (x[i]==0 )
-- bxsize;
else
break ;
}
for (i=ysize-1;i>=0;-- i)
{
if (y[i]==0 )
-- bysize;
else
break ;
}
if (bxsize< bysize)
{
std::swap(bxsize,bysize);
std::swap(xsize,ysize);
std::swap(x,y);
}
xsize= bxsize;
const long csABigMulSize=1000 ;
if ( (bysize<csABigMulSize)||(bxsize*2>=bysize*3)||(bxsize> ysize) )
ysize= bysize;
else
ysize= bxsize;
}
TLargeFloat::SelfType& TLargeFloat::operator *= (const SelfType& Value)
{
long xsize= m_Digits.size();
long ysize= Value.m_Digits.size();
if ((m_Sign==0)||(Value.m_Sign==0 ))
{
if (m_Sign!=0 )
this-> Zero();
if (xsize< ysize)
m_Digits.resize(ysize,0 );
return *this ;
}
if (xsize< ysize)
m_Digits.resize(ysize,0 );
long rminsize=std::max(xsize,ysize)+2;//乘法结果需要的位数
const TInt32bit* x=&m_Digits[0 ];
const TInt32bit* y=&Value.m_Digits[0 ];
getBestMulSize(x,xsize,y,ysize);
if (rminsize>xsize+ ysize)
rminsize=xsize+ ysize;
TArray tempArray(rminsize);
ArrayMUL(&tempArray[0 ],rminsize,x,xsize,y,ysize);
xsize= m_Digits.size();
long resultsize= std::min(xsize,rminsize);
long i;
for (i=0;i<resultsize;++i) this->m_Digits[i]= tempArray[i];
for (i=resultsize;i<xsize;++i) this->m_Digits[i]=0 ;
m_Exponent+= Value.m_Exponent;
m_Sign*= Value.m_Sign;
Canonicity();
return *this ;
}
// 快速傅立叶变换实现大整数乘法
// FFT Mul
struct TComplex //复数类型
{
double i;
double r;
};
//初始化
void FFTInitial(TComplex* w,long* lst,const long n)
{
//计算W^i , i in [0--n)
const double PI=3.1415926535897932385 ;
const double seta=2.0*PI/ n;
long i,j;
long n2=n>>2 ;
for (i=0;i<=n2;++ i)
{
w[i].i=sin(seta* i);
w[i].r=cos(seta* i);
}
for (j=(n2+1),i=(n2-1); i>=0 ;--i,++ j)
{
w[j].i= w[i].i;
w[j].r=- w[i].r;
}
//计算排序用数组
lst[0]=0 ;
i=1 ;
long m;
for (n2=n>>1,m=2; n2>0 ;n2=n2>>1,m =m<<1 )
{
for (long j=0;i<m;++i,++ j)
{
lst[i]=lst[j]+ n2;
}
}
}
//快速傅立叶变换
void FFT(TComplex* a,const TComplex* w,const long n)
{
long n2=1 ;
long n1=n >> 1 ;
for (long per=1;per< n;)
{
long m=n2; long j=0; long k= n2;
per<<=1 ;
while (k< n)
{
for (long i2=0; j<m ;++j,++k,i2+= n1)
{
TComplex tmpb= a[j];
double tmp1=a[k].r*w[i2].r-a[k].i* w[i2].i;
double tmp2=a[k].r*w[i2].i+a[k].i* w[i2].r;
a[j].r=tmpb.r+ tmp1;
a[j].i=tmpb.i+ tmp2;
a[k].r=tmpb.r- tmp1;
a[k].i=tmpb.i- tmp2;
}
m+= per;
j+= n2;
k+= n2;
}
n2= per;
n1>>=1 ;
}
}
//反向快速傅立叶变换
void InvFFT(TComplex* a,const TComplex* w,const long n)
{
for (long i=0;i<n;++ i)
a[i].i=- a[i].i;
FFT(a,w,n);
}
void FFT_Convolution(const TComplex* a,TComplex* b,const long n)
{
for (long i=0;i<n;++ i)
{
double br=a[i].r*b[i].r - a[i].i* b[i].i;
b[i].i=a[i].r*b[i].i + a[i].i* b[i].r;
b[i].r= br;
}
}
void FFT_IntArrayCopyToComplexArray(const TInt32bit* ACoef,const long ASize,TComplex* result,const long n,const long* lst)
{
for (long i=0;i<n;++ i)
{
long ai= lst[i];
if (ai< ASize)
result[i].r= ACoef[ai];
else
result[i].r =0.0 ;
result[i].i=0.0 ;
}
}
void FFT_ComplexArrayToIntArray(const TComplex* cmx,const long n,TInt32bit* result,const long rMinSize)
{
const double tmpRevN=1.0/ n;
double FFT_int_base;
TLargeFloat::TArray tempResult;
TInt32bit* dst=0 ;
long dstsize=0 ;
{
FFT_int_base=(long )TLargeFloat::emBase;
dstsize= rMinSize;
dst= result;
}
const double tmpRevFFT_int_base=1.0/ FFT_int_base;
double MaxWorstEr=0 ;
double tmp=0.0 ;
for (long i=std::min(n,dstsize)-1;i>=1;-- i)
{
double num =cmx[i-1].r*tmpRevN+ tmp;
tmp=floor((num+0.499)* tmpRevFFT_int_base);
dst[i]=(TInt32bit)(num+0.499-tmp* FFT_int_base);
double newWorstEr=abs(num-tmp*FFT_int_base-dst[i]);//记录最大误差
if (newWorstEr> MaxWorstEr)
MaxWorstEr= newWorstEr;
}
if (dstsize>0 )
dst[0]=(TInt32bit)(tmp+0.1 );
if (MaxWorstEr>=0.499 )
throw TLargeFloat::TException("ERROR:FFT's FFT_ComplexArrayToIntArray(); "); //误差过大
}
//FFT平方
void SquareFFT(const TInt32bit* ACoef,const long ASize,TInt32bit* CCoef,const long CMinSize)
{
long ansize=ASize+ ASize;
long n=1 ;
while (n<ansize) n<<=1 ;
std::vector<TComplex> _w((n>>1)+1 );
std::vector<long> _lst(n);
TComplex* w=&_w[0 ];
long* lst=&_lst[0 ];
FFTInitial(w,lst,n);
std::vector<TComplex> _a(n);
TComplex* a=&_a[0 ];
FFT_IntArrayCopyToComplexArray(ACoef,ASize,a,n,lst);
FFT(a,w, n);
FFT_Convolution(a,a,n);
std::vector<TComplex> _tmpa(n);
_tmpa.swap(_a);
TComplex* tmpa=&_tmpa[0]; a=&_a[0 ];
for (long i=0;i<n;++i) a[i]= tmpa[lst[i]];
_tmpa.clear();
_lst.clear();
InvFFT(a,w,n);
_w.clear();
FFT_ComplexArrayToIntArray(a,n,CCoef,CMinSize);
}
//FFT乘法
void MulFFT(const TInt32bit* ACoef,const long ASize,const TInt32bit* BCoef,const long BSize,TInt32bit* CCoef,const long CMinSize)
{
long absize=(ASize+ BSize);
long n=1 ;
while (n<absize) n<<=1 ;
std::vector<TComplex> _w((n>>1)+1 );
std::vector<long> _lst(n);
TComplex* w=&_w[0 ];
long* lst=&_lst[0 ];
FFTInitial(w,lst,n);
std::vector<TComplex> _a(n);
TComplex* a=&_a[0 ];
FFT_IntArrayCopyToComplexArray(ACoef,ASize,a,n,lst);
std::vector<TComplex> _b(n);
TComplex* b=&_b[0 ];
FFT_IntArrayCopyToComplexArray(BCoef,BSize,b,n,lst);
FFT(b,w, n);
FFT(a,w, n);
FFT_Convolution(a,b,n);
for (long i=0;i<n;++i) a[i]= b[lst[i]];
_b.clear();
_lst.clear();
InvFFT(a,w,n);
_w.clear();
FFT_ComplexArrayToIntArray(a,n,CCoef,CMinSize);
}
/
const long csBestMUL_ExE_size =1024 / TLargeFloat::em10Power;
const long csBestMUL_Dichotomy_size =4096 / TLargeFloat::em10Power;
const long csBestMul_FFT4Max_size =16777216 / TLargeFloat::em10Power;
void ArrayMUL(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize)
{
if (xsize< ysize)
{
std::swap(xsize,ysize);
std::swap(x,y);
}
if (rminsize< ysize)
{
xsize= rminsize;
ysize= rminsize;
}
if (ysize<=csBestMUL_ExE_size) //
TLargeFloat_ArrayMUL_ExE(result,rminsize,x,xsize,y,ysize);
else if (ysize<= csBestMUL_Dichotomy_size)
ArrayMUL_DichotomyPart(result,rminsize,x,xsize,y,ysize);
else if ((xsize+ysize)<=(csBestMul_FFT4Max_size*2 ))
{
if (x== y)
SquareFFT(x,xsize,result,rminsize);
else
MulFFT(x,xsize,y,ysize,result,rminsize);
}
else
ArrayMUL_DichotomyPart(result,rminsize,x,xsize,y,ysize);
}
void LargeFloat_UnitTest()
{
// 单元测试
// 测试先行... 但作者太懒...
//todo:
TLargeFloat x( 200,TLargeFloat::TDigits(100 ));
TLargeFloat y(12345.678987654321,TLargeFloat::TDigits(100 ));
//TLargeFloat z("-12345.678987654321e-100",TLargeFloat::TDigits(100));
TLargeFloat z( "99999999999999999999999999999999999999999999",TLargeFloat::TDigits(200 ));
//
}
// TLargeFloat.cpp: implementation of the TLargeFloat class.
// 超高精度浮点数类TLargeFloat
//
#include "TLargeFloat.h"
#include <algorithm>
//#include "assert.h"
#include <math.h>
// #define MyDebugAssert(b) { if (!(b)) __asm{ int 3 } }
//用以控制运算精度的工具
class TDigitsLengthCtrl
{
private :
std::vector<TLargeFloat*> m_list;
public :
inline void add_to_ctrl(TLargeFloat* var) { m_list.push_back(var); }
void SetDigitsLength(const long uiDigitsLength)
{
long size= m_list.size();
for (long i=0;i<size;++ i)
m_list[i]-> SetDigitsLength(uiDigitsLength);
}
};
//自动精度控制
class TDigitsLengthAutoCtrl:public TDigitsLengthCtrl
{
private :
std::vector<long> m_DigitsLengthList;
long step;
public :
TDigitsLengthAutoCtrl(long DigitsMul,long DigitsLength0,long MaxDigitsLength)//(收敛系数,初始精度,最终需要精度)
{
// MyDebugAssert(DigitsLength0>0);
//得到最佳的精度梯度
long curDigitsLength= MaxDigitsLength;
while (curDigitsLength> DigitsLength0)
{
m_DigitsLengthList.push_back(curDigitsLength);
if ((DigitsLength0<=1)&&(curDigitsLength==1)) break ;
curDigitsLength=(curDigitsLength+DigitsMul-1)/ DigitsMul;
}
step=get_runcount()-1 ;
}
inline long get_runcount() { return m_DigitsLengthList.size(); }
inline void SetNextDigits()
{
//MyDebugAssert(step>=0);
long DigitsLength= m_DigitsLengthList[step];
if (step>0 )
DigitsLength+=4 ;
SetDigitsLength(DigitsLength);
-- step;
if (step<0) step=0 ;
}
};
/
void TLargeFloat_CtrlExponent(TLargeFloat::TArray& v,TMaxInt iMoveRightCount)
{
//iMoveCountBig 有可能存不下 但现在的体系下因右移超过值域比较难
long iMoveCountBig=(long)(iMoveRightCount/ TLargeFloat::em10Power);
long iMoveCountSmall=(long)(iMoveRightCount% TLargeFloat::em10Power);
//大的右移
if (iMoveCountBig>0 )
{
for (long i=v.size()-1;i>=iMoveCountBig;-- i)
v[i]=v[i- iMoveCountBig];
for (long j=0;j<iMoveCountBig;++ j)
v[j]=0 ;
}
//小的右移
if (iMoveCountSmall>0 )
{
TInt32bit iDiv=1 ;
for (long j=0;j<iMoveCountSmall;++j) iDiv*=10 ;
long v_size= v.size();
for (long i=iMoveCountBig;i<v_size-1;++ i)
{
v[i+1]+=(v[i]%iDiv)* TLargeFloat::emBase;
v[i]/= iDiv;
}
if (v_size>=1 )
v[v_size-1]/= iDiv;
}
}
void TLargeFloat_ArrayAddTestLast(TInt32bit* x,long xsize)
{
for (long i=xsize-1;i>0;-- i)
{
if (x[i]>=TLargeFloat::emBase)//进位
{
++x[i-1 ];
x[i]-= TLargeFloat::emBase;
}
else
break ;
}
}
void TLargeFloat_ArrayAdd(TInt32bit* result,long rsize,const TInt32bit* y,long ysize)
{
// MyDebugAssert(rsize>=ysize);
//MyDebugAssert(ysize>0);
TInt32bit* ri=&result[rsize- ysize];
long i;
for (i=ysize-1;i>0;-- i)
{
TInt32bit r=ri[i]+ y[i];
if (r>=TLargeFloat::emBase)//进位
{
++ri[i-1 ];
r-= TLargeFloat::emBase;
}
ri[i]= r;
}
ri[0]+=y[0 ];
TLargeFloat_ArrayAddTestLast(result,rsize-ysize+1 );
}
void TLargeFloat_ArraySub(TInt32bit* result,long rsize,const TInt32bit* y,long ysize)
{
// MyDebugAssert(rsize>=ysize);
//MyDebugAssert(ysize>0);
TInt32bit* ri=&result[rsize- ysize];
long i;
for (i=ysize-1;i>0;-- i)
{
TInt32bit r=ri[i]- y[i];
if (r<0)//借位
{
--ri[i-1 ];
r+= TLargeFloat::emBase;
}
ri[i]= r;
}
ri[0]-=y[0 ];
for (i=rsize-ysize;i>0;-- i)
{
if (result[i]<0)//借位
{
--result[i-1 ];
result[i]+= TLargeFloat::emBase;
}
else
break ;
}
}
TInt32bit _inti_csMaxMuliValue()
{
double rb=1; double mb=1 ;
for (long i=0;i<100/TLargeFloat::em10Power;++ i)
{
mb*=(1.0/ TLargeFloat::emBase);
rb+= mb;
}
return (TInt32bit)( TInt32bit_MAX_VALUE*(1.0/(TLargeFloat::emBase-1))/rb ) -1 ;
}
//不超界所允许的乘数值M满足: (emBase-1)*M + (emBase-1)*M/B + (emBase-1)*M/B^2 + (emBase-1)*M/B^3 ... <=TInt32bit_MAX_VALUE
static const TInt32bit csMaxMuliValue= _inti_csMaxMuliValue();
static const TInt32bit csMaxMulAddValue = csMaxMuliValue - (TLargeFloat::emBase-1 );
void TLargeFloat_ArrayMUL_ExE(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize)
{
//N*N复杂度的简单乘法实现
for (long k=0;k<rminsize;++k) result[k]=0 ;
while ((ysize>0)&&(y[0]==0)) { --ysize; ++y; ++result; -- rminsize;}
//while ((xsize>0)&&(x[0]==0)) { --xsize; ++x; ++result; --rminsize;}
while ((ysize>0)&&(y[ysize-1]==0)) { -- ysize; }
//while ((xsize>0)&&(x[xsize-1]==0)) { --xsize; }
long add_sum=0 ;
for (long i=0;i<xsize;++ i)
{
long xi= x[i];
if (xi>0 )
{
TInt32bit* resulti=&result[i+1 ];
long y_limit=std::min(rminsize-1- i,ysize);
for (long j=0;j<y_limit;++ j)
{
resulti[j]+=(xi* y[j]);
}
add_sum+= xi;
if (add_sum> csMaxMulAddValue)
{
for (long k=i+y_limit;k>0;-- k)
{
TInt32bit v= result[k];
if (v>= TLargeFloat::emBase)
{
result[k-1]+=v/ TLargeFloat::emBase;
result[k]= v% TLargeFloat::emBase;
}
}
add_sum=0 ;
}
}
}
if (add_sum>0 )
{
for (long k=rminsize-1;k>0;-- k)
{
TInt32bit v= result[k];
if (v>= TLargeFloat::emBase)
{
result[k-1]+=v/ TLargeFloat::emBase;
result[k]= v% TLargeFloat::emBase;
}
}
}
}
//数组乘法 核心
void ArrayMUL(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize);
void ArrayMUL_Dichotomy(TInt32bit* result,long rminsize,const TInt32bit* x,const TInt32bit* y,long MulSize)
{
// 二分法的乘法实现
// x*y=(a*E+b)*(c*E+d)=(E*E-E)*ac + E*(a+b)*(c+d) -(E-1)*bd
// temp_a_add_b=a+b;
// temp_c_add_d=c+d;
// result=E*temp_a_add_b*temp_c_add_d;
// temp_ac=a*c;
// result+=E*E*temp_ac;
// result-=E*temp_ac;
// temp_bd=b*d;
// result+=temp_bd;
// result-=E*temp_bd;
//
long i;
const long E=((MulSize+1)>>1 );
//if (tmpData+2*(E+1)>end_tmpData) __asm int 3
const long acSize=MulSize- E;
const long acErrorSize=E- acSize;
const TInt32bit* a= x;
const TInt32bit* b=& x[acSize];
const TInt32bit* c= y;
const TInt32bit* d=& y[acSize];
TLargeFloat::TArray _tmpData((E+1)*2 );
TInt32bit* tmpData=&_tmpData[0 ];
TInt32bit* temp_a_add_b=&tmpData[0 ];
TInt32bit* temp_c_add_d=&tmpData[(E+1 )];
temp_a_add_b[0]=0 ;
for (i=0;i<E;++i) temp_a_add_b[i+1]= b[i];
TLargeFloat_ArrayAdd(temp_a_add_b,1+E,a,E- acErrorSize);
temp_c_add_d[0]=0 ;
for (i=0;i<E;++i) temp_c_add_d[i+1]= d[i];
TLargeFloat_ArrayAdd(temp_c_add_d,1+E,c,E- acErrorSize);
const long abcdPos=(2*MulSize-E-2*(E+1 ));
for (i=0;i<abcdPos;++i) result[i]=0 ;
ArrayMUL(&result[abcdPos],std::min(rminsize-abcdPos,2*(E+1)),temp_a_add_b,E+1,temp_c_add_d,E+1 );
for (i=abcdPos+2*(E+1);i<rminsize;++i) result[i]=0 ;
TInt32bit* temp_ac=&tmpData[0 ];
const long acminsize=std::min(rminsize,acSize*2 );
ArrayMUL(temp_ac,acminsize,a,acSize,c,acSize);
TLargeFloat_ArrayAdd(result,acminsize,temp_ac,acminsize);
long sub_ac_size=acSize*2 ;
if (E+sub_ac_size>rminsize) sub_ac_size=rminsize- E;
TLargeFloat_ArraySub(result,E+ sub_ac_size,temp_ac,sub_ac_size);
const long add_bdPos=2*MulSize-2* E;
long sub_bd_size=2* E;
const long sub_bdPos=add_bdPos- E;
if (sub_bdPos+sub_bd_size>rminsize) sub_bd_size=rminsize- sub_bdPos;
if (sub_bd_size>0 )
{
TInt32bit* temp_bd=&tmpData[0 ];
ArrayMUL(temp_bd,sub_bd_size,b,E,d,E);
long add_bd_size=2* E;
if (add_bdPos+add_bd_size>rminsize) add_bd_size=rminsize- add_bdPos;
if (add_bd_size>0 )
TLargeFloat_ArrayAdd(result,add_bdPos+ add_bd_size,temp_bd,add_bd_size);
TLargeFloat_ArraySub(result,sub_bdPos+ sub_bd_size,temp_bd,sub_bd_size);
}
}
void ArrayMUL_DichotomyPart(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize)
{
//二分法的辅助函数
///
//x*y=(a*E+b)*y=a*y*E+b*y;
if (xsize== ysize)
{
ArrayMUL_Dichotomy(result,rminsize,x,y,ysize);
return ;
}
if (xsize< ysize)
{
std::swap(xsize,ysize);
std::swap(x,y);
}
const long E= ysize;
const long asize=xsize- E;
const TInt32bit* a=&x[0 ];
const TInt32bit* b=& x[asize];
ArrayMUL(result,rminsize,a,asize,y,ysize);
for (long i=asize+ysize;i<rminsize;++i) result[i]=0 ;
const long byPos= asize;
if (byPos< rminsize)
{
const long byminsize=rminsize- byPos;
TLargeFloat::TArray tmpData(byminsize);
TInt32bit* tmp_by=&tmpData[0 ];
ArrayMUL_Dichotomy(tmp_by,byminsize,b,y,E);
TLargeFloat_ArrayAdd(result,rminsize,tmp_by,byminsize);
}
}
/
const long csTMaxInt_Digits=(long)(log10((long double)TMaxInt_MAX_VALUE)+1 );
TLargeFloat::TLargeFloat(const SelfType& Value)
:m_Digits(Value.m_Digits)
{
m_Exponent= Value.m_Exponent;
m_Sign= Value.m_Sign;
}
TLargeFloat::TLargeFloat(const long double DefultValue)
:m_Digits(TDigits(emLongDoubleDigits+1).GetDigitsArraySize(),0 )
{
fToLargeFloat(DefultValue);
}
TLargeFloat::TLargeFloat(const long double DefultValue,const TDigits& DigitsLength)
:m_Digits(DigitsLength.GetDigitsArraySize(),0 )
{
fToLargeFloat(DefultValue);
}
TLargeFloat::TLargeFloat(const char* strValue)
:m_Digits(TDigits(csTMaxInt_Digits).GetDigitsArraySize(),0 )
{
sToLargeFloat(std::string (strValue));
}
TLargeFloat::TLargeFloat(const char* strValue,const TDigits& DigitsLength)
:m_Digits(DigitsLength.GetDigitsArraySize(),0 )
{
sToLargeFloat(std::string (strValue));
}
TLargeFloat::TLargeFloat(const std::string& strValue)
:m_Digits(TDigits(csTMaxInt_Digits).GetDigitsArraySize(),0 )
{
sToLargeFloat(strValue);
}
TLargeFloat::TLargeFloat(const std::string& strValue,const TDigits& DigitsLength)
:m_Digits(DigitsLength.GetDigitsArraySize(),0 )
{
sToLargeFloat(strValue);
}
void TLargeFloat::Zero()
{
if (m_Sign==0) return ;
m_Sign=0 ;
m_Exponent=0 ;
long old_size= m_Digits.size();
for (long i=0;i<old_size;++ i)
m_Digits[i]=0 ;
}
void TLargeFloat::Canonicity()
{
// 规格化 小数部分
// 规格化前允许:m_Digits[0]>=emBase 也就是小数部分的值大于等于1.0;
// 规格化前允许:m_Digits[]前面有多个0值 也就是小数部分的值小于0.1;
//规格化后的数满足的条件:小数部分的值 小于1.0,大于等于0.1;
if (m_Sign==0 )
{
return ;
}
long old_size= m_Digits.size();
if (old_size<=0) return; //不可能发生:)
if ( (m_Digits[0]<emBase)&&(m_Digits[0]>=(emBase/10)) ) return ;
//处理右移
while (m_Digits[0]>=emBase)//是否需要右移1
{
m_Exponent+= em10Power;
for (long i=old_size-1;i>=2;-- i)
m_Digits[i]=m_Digits[i-1 ];
if (old_size>=2) m_Digits[1]=m_Digits[0] % emBase;
m_Digits[0]/= emBase;
}
// 考虑左移
//大的左移
long iMoveCountBig= old_size;
for (long i=0;i<old_size;++ i)
{
if (m_Digits[i]!=0 )
{
iMoveCountBig= i;
break ;
}
}
if (iMoveCountBig== old_size)
{
//as Zero();
m_Sign=0 ;
m_Exponent=0 ;
return ;
}
if (iMoveCountBig>0 )
{
m_Exponent-=(iMoveCountBig* em10Power);
for (long j=0;j<old_size-iMoveCountBig;++ j)
m_Digits[j]=m_Digits[j+ iMoveCountBig];
for (long k=old_size-iMoveCountBig;k<old_size;++ k)
m_Digits[k]=0 ;
}
//小的左移
TInt32bit iMoveMul=1 ;
long iMoveCountSmall=0 ;
while (iMoveMul*m_Digits[0]<(emBase/10 ))
{
iMoveMul*=10 ;
++ iMoveCountSmall;
}
if (iMoveCountSmall>0 )
{
m_Exponent-= iMoveCountSmall;
for (long i=old_size-1;i>=0;-- i)
m_Digits[i]*= iMoveMul;
for (long j=old_size-1;j>0;-- j)
{
TInt32bit value= m_Digits[j];
m_Digits[j]=value% emBase;
m_Digits[j-1]+=value/ emBase;
}
}
}
void TLargeFloat::iToLargeFloat(TMaxInt iValue)
{
Zero();
long new_size= TDigits(csTMaxInt_Digits).GetDigitsArraySize();
if ((long)m_Digits.size()< new_size)
m_Digits.resize(new_size,0 );
if (iValue==0 )
return ;
else if (iValue>0 )
m_Sign=1 ;
else
{
m_Sign =-1 ;
iValue=- iValue;
}
//无误差转换
TMaxInt tmp_iValue= iValue;
long n=0 ;
for (;tmp_iValue!=0;++ n)
tmp_iValue/= emBase;
m_Exponent=n* em10Power;
for (long i=0;i<n;++ i)
{
m_Digits[n-1-i]=(TInt32bit)(iValue% emBase);
iValue/= emBase;
}
Canonicity();
}
void TLargeFloat::fToLargeFloat(long double fValue)
{
TMaxInt iValue= (TMaxInt)fValue;
if (iValue== fValue)
{
iToLargeFloat(iValue);
return ;
}
Zero();
long new_size=TDigits(emLongDoubleDigits+1 ).GetDigitsArraySize();
if ((long)m_Digits.size()< new_size)
m_Digits.resize(new_size,0 );
if (fValue==0 )
return ;
else if (fValue>0 )
m_Sign=1 ;
else
{
m_Sign =-1 ;
fValue=- fValue;
}
m_Exponent=(long )floor(log10(fValue));
fValue/=pow(10.0,(long )m_Exponent.AsInt());
long size= m_Digits.size();
for (long i=0;i<size;++i)//得到小数位
{
if (fValue<=0) break ;
fValue*= emBase;
TInt32bit iValue= (TInt32bit)floor(fValue);
fValue-= iValue;
m_Digits[i]= iValue;
}
Canonicity();
}
void TLargeFloat::Swap(SelfType& Value)
{
if (this==&Value) return ;
m_Digits.swap(Value.m_Digits);
std::swap(m_Sign,Value.m_Sign);
std::swap(m_Exponent,Value.m_Exponent);
}
void TLargeFloat::Chs()
{
m_Sign*=(-1 );
}
void TLargeFloat::Abs()
{
if (m_Sign!=0) m_Sign=1 ;
}
unsigned long TLargeFloat::GetDigitsLength() const
{
return m_Digits.size()* em10Power;
}
void TLargeFloat::SetDigitsLength(const TDigits& DigitsLength)
{
m_Digits.resize(DigitsLength.GetDigitsArraySize(),0 );
}
TLargeFloat::SelfType& TLargeFloat::operator = (const SelfType& Value)
{
if (this==&Value) return *this ;
m_Digits= Value.m_Digits;
m_Sign= Value.m_Sign;
m_Exponent= Value.m_Exponent;
return *this ;
}
TLargeFloat::SelfType& TLargeFloat::operator = (long double fValue)
{
fToLargeFloat(fValue);
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*pow((long double)10.0,(long double )m_Exponent.AsInt());
long double r=1 ;
long double Sum=0 ;
long old_size= m_Digits.size();
for (long i=0;i<old_size;++i)//得到小数位
{
r/=emBase;//r*=(1.0/emBase);
if (r==0) break ;
Sum+=(m_Digits[i]* r);
}
return result* Sum;
}
std::string TLargeFloat::AsString() const
{
if (m_Sign==0 )
return "0" ;
//计算需要的字符串空间大小
long str_length=2+m_Digits.size()* em10Power;
if (m_Sign<0) ++str_length; //负号
TMaxInt EpValue = m_Exponent.AsInt();
long UEP_StrLength=0 ;
if (EpValue!=0 )
{
++ str_length;
if (EpValue<0 )
{
EpValue=- EpValue;
++ str_length;
}
UEP_StrLength=0 ;
while (EpValue>0 )
{
EpValue/=10 ;
++ UEP_StrLength;
}
str_length+= UEP_StrLength;
}
std::string result(str_length,' ' );
std::string::value_type* pStr=&result[0 ];
//输出字符串
if (m_Sign<0) { *pStr='-'; ++ pStr; }
*pStr='0'; ++pStr; *pStr='.'; ++ pStr;
long dgsize= m_Digits.size();
for (long i=0;i<dgsize;++ i)
{
TInt32bit Value= m_Digits[i];
for (long d=0;d<em10Power;++ d)
{
pStr[em10Power-1-d]=(char)('0'+(Value%10 ));
Value/=10 ;
}
pStr+= em10Power;
}
EpValue= m_Exponent.AsInt();
if (EpValue!=0 )
{
*pStr='e'; ++ pStr;
if (EpValue<0 )
{
EpValue=- EpValue;
*pStr='-'; ++ pStr;
}
for (long i=0;i<UEP_StrLength;++ i)
{
pStr[UEP_StrLength-1-i]=(char)('0'+(EpValue%10 ));
EpValue/=10 ;
}
pStr+= UEP_StrLength;
}
return result;
}
template<class PChar>
PChar sToLargeFloat_GetCharIntEnd(PChar int_begin,PChar str_end)
{
long int_count=0 ;
for (PChar i=int_begin;i<str_end;++ i)
{
if ( ('0'<=(*i)) && ((*i)<='9' ) )
++ int_count;
else
break ;
}
return & int_begin[int_count];
}
inline void sToLargeFloat_setAChar(TLargeFloat::TArray& Digits,long set_index,char aChar)
{
unsigned long Value=aChar-'0' ;
long e10Power_count=TLargeFloat::em10Power-1-(set_index% TLargeFloat::em10Power);
for (long i=0;i<e10Power_count;++ i)
Value*=10 ;
Digits[set_index/TLargeFloat::em10Power]+= Value;
}
void TLargeFloat::sToLargeFloat(const std::string& strValue)
{
if (strValue.size()<=0 )
{
this-> Zero();
return ;
}
typedef const std::string::value_type* PChar;
PChar pstr_begin= strValue.c_str();
PChar pstr_end=& pstr_begin[strValue.size()];
//str as: [+|-][0..9][.][0..9][E|e][+|-][0..9]
bool is_have_sign=false ;
long sign=1 ;
bool is_have_int=false ;
PChar int_begin=0; PChar int_end=0 ;
bool is_have_dot=false ;
bool is_have_digits=false ;
PChar digits_begin=0; PChar digits_end=0 ;
bool is_have_ep=false ;
bool is_have_ep_sign=false ;
long ep_sign=1 ;
bool is_have_ep_int=false ;
PChar ep_int_begin=0; PChar ep_int_end=0 ;
//处理正负号
if ((*pstr_begin)=='-' )
{
sign = -1 ;
is_have_sign=true ;
++ pstr_begin;
}
else if ((*pstr_begin)=='+' )
{
is_have_sign=true ;
++ pstr_begin;
}
//处理前面的整数部分
int_begin= pstr_begin;
int_end= sToLargeFloat_GetCharIntEnd(int_begin,pstr_end);
is_have_int=(int_begin!= int_end);
if ((int_end-int_begin>=2)&&((*int_begin)=='0')) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 0"); //'0?'数字表示错误
pstr_begin= int_end;
if (((*pstr_begin)!='.')&&(!is_have_int)) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 1"); // 没有任何数字
//处理小数部分
if ((*pstr_begin)=='.' )
{
is_have_dot=true ;
++ pstr_begin;
digits_begin= pstr_begin;
digits_end= sToLargeFloat_GetCharIntEnd(digits_begin,pstr_end);
is_have_digits=(digits_begin!= digits_end);
if ((!is_have_digits)&&(!is_have_int)) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 2"); //没有任何数字
pstr_begin= digits_end;
}
//处理指数部分
if ( ((*pstr_begin)=='e')||((*pstr_begin)=='E' ) )
{
is_have_ep=true ;
++ pstr_begin;
//处理指数的正负号
if ((*pstr_begin)=='-' )
{
ep_sign = -1 ;
is_have_ep_sign=true ;
++ pstr_begin;
}
else if((*pstr_begin)=='+' )
{
is_have_ep_sign=true ;
++ pstr_begin;
}
//处理指数中的整数
ep_int_begin= pstr_begin;
ep_int_end= sToLargeFloat_GetCharIntEnd(ep_int_begin,pstr_end);
is_have_ep_int=(ep_int_begin!= ep_int_end);
if ((ep_int_end-ep_int_begin>=2)&&((*ep_int_begin)=='0')) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 3"); //'0?'数字表示错误
pstr_begin= ep_int_end;
if (!is_have_ep_int) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 4"); //指数没有数字
}
if (pstr_begin!=pstr_end) throw TException("ERROR:TLargeFloat::sToLargeFloat(); 5"); //未预料的字符
//
//实际的类型转换
this-> Zero();
this->m_Sign= sign;
this->m_Exponent=(int_end- int_begin);
long need_digits_count=(int_end-int_begin)+(digits_end- digits_begin);
if ((long)this->GetDigitsLength()< need_digits_count)
this-> SetDigitsLength(need_digits_count);
long set_index=0 ;
PChar set_begin= int_begin;
for (;set_begin<int_end;++set_begin,++ set_index)
sToLargeFloat_setAChar(this->m_Digits,set_index,* set_begin);
set_begin= digits_begin;
for (;set_begin<digits_end;++set_begin,++ set_index)
sToLargeFloat_setAChar(this->m_Digits,set_index,* set_begin);
if (is_have_ep)
{
TExpInt ep=0 ;
for (PChar set_begin=ep_int_begin;set_begin<ep_int_end;++ set_begin)
{
ep*=10 ;
ep+=((*set_begin)-'0' );
}
ep*= ep_sign;
this->m_Exponent+= ep;
}
Canonicity();
}
long TLargeFloat::Compare(const SelfType& Value) const
{
if (this==&Value) return 0 ;
// (*this)>Value 返回1,小于返回-1,相等返回0
//比较符号
if (m_Sign> Value.m_Sign)
return 1 ;
else if(m_Sign< Value.m_Sign)
return -1 ;
else //m_Sign==Value.m_Sign
{
if(m_Sign==0 )
return 0 ;
}
// m_Sign==Value.m_Sign
//比较指数
if (m_Exponent.AsInt()> Value.m_Exponent.AsInt())
return m_Sign;
else if (m_Exponent.AsInt()< Value.m_Exponent.AsInt())
return - m_Sign;
else//(m_Exponent==Value.m_Exponent)
{
long sizeS= m_Digits.size();
long sizeV= Value.m_Digits.size();
long min_size= std::min(sizeS,sizeV);
for (long i=0;i<min_size;++ i)
{
if (m_Digits[i]!= Value.m_Digits[i])
{
if (m_Digits[i]> Value.m_Digits[i])
return m_Sign;
else //if (m_Digits[i]<Value.m_Digits[i])
return - m_Sign;
}
}
//继续比较 处理尾部
if (sizeS> sizeV)
{
for (long i=sizeV;i<sizeS;++ i)
{
if (m_Digits[i]>0 )
return m_Sign;;
}
}
else if (sizeS< sizeV)
{
for (long i=sizeS;i<sizeV;++ i)
{
if (Value.m_Digits[i]>0 )
return - m_Sign;
}
}
//sizeS==sizeV
return 0 ;
}
}
//
//+ -
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)
{
TInt32bit oldSign= m_Sign;
Abs_Add(Value);
m_Sign= oldSign;
return *this ;
}
else
return *this-=(- Value);
}
TLargeFloat::SelfType& TLargeFloat::operator -= (const SelfType& Value)
{
if (Value.m_Sign==0 )
return (*this );
else if (m_Sign==0 )
{
(*this)=- Value;
return (*this );
}
else if (m_Sign== Value.m_Sign)
{
long comResult=this-> Compare(Value);
if (comResult==0 )
{
this-> Zero();
}
else
{
Abs_Sub_Abs(Value);
m_Sign = comResult;
}
return *this ;
}
else
return *this+=(- Value);
}
void TLargeFloat::Abs_Add(const SelfType& Value)//绝对值加法
{
this-> Abs();
SelfType Right(Value);
Right.Abs();
//精度一致
if (m_Digits.size()< Right.m_Digits.size())
m_Digits.resize(Right.m_Digits.size(),0 );
else if (m_Digits.size()> Right.m_Digits.size())
Right.m_Digits.resize(m_Digits.size(),0 );
//被加数指数较大就可以了
if (m_Exponent.AsInt()< Right.m_Exponent.AsInt())
this-> Swap(Right);
long size= m_Digits.size();
TMaxInt iMoveRightCount=m_Exponent.AsInt()- Right.m_Exponent.AsInt();
if (iMoveRightCount>=size*(TMaxInt)TLargeFloat::em10Power) return ;
TLargeFloat_CtrlExponent(Right.m_Digits,iMoveRightCount);//对齐小数点
TLargeFloat_ArrayAdd( &m_Digits[0],size,&Right.m_Digits[0 ],size);
if (m_Digits[0]>= emBase)
Canonicity();
}
void TLargeFloat::Abs_Sub_Abs(const SelfType& Value)//绝对值减法
{
this-> Abs();
SelfType Right(Value);
Right.Abs();
long comResult=this-> Compare(Right);
if (comResult==0 )
{
this-> Zero();
return ;
}
else if (comResult<0 )
this-> Swap(Right);
//精度一致
if (m_Digits.size()< Right.m_Digits.size())
m_Digits.resize(Right.m_Digits.size(),0 );
else if (m_Digits.size()> Right.m_Digits.size())
Right.m_Digits.resize(m_Digits.size(),0 );
long size= m_Digits.size();
TMaxInt iMoveRightCount=m_Exponent.AsInt()- Right.m_Exponent.AsInt();
if (iMoveRightCount>=size*(TMaxInt)TLargeFloat::em10Power) return ;
TLargeFloat_CtrlExponent(Right.m_Digits,iMoveRightCount); //对齐小数点
TLargeFloat_ArraySub( &m_Digits[0],size,&Right.m_Digits[0 ],size);
if (m_Digits[0]*10< emBase)
Canonicity();
}
/
// /
//最大的32bit整数除数M满足: (emBase-1)+(M-1)*emBase<=TInt32bit_MAX_VALUE
const TInt32bit csMaxDiviValue=TInt32bit_MAX_VALUE/TLargeFloat::emBase -1 ;
//最大的整数除数M满足: (emBase-1)+(M-1)*emBase<=TMaxInt_MAX_VALUE
const TMaxInt csMaxDiviValueBig=TMaxInt_MAX_VALUE/TLargeFloat::emBase -1 ;
void TLargeFloat::DivInt(TMaxInt iValue)//除以一个整数
{
if (iValue==0 )
throw TException("ERROR:TLargeFloat::DivInt()" );
else if (iValue<0 )
{
iValue=- iValue;
this-> Chs();
//continue
}
if (iValue==1) return ;
if (this->m_Sign==0) return ;
if (iValue> csMaxDiviValueBig)
{
TLargeFloat y(0.0 );
y.iToLargeFloat(iValue);
(*this)/= y;
return ;
}
if (iValue<= csMaxDiviValue)
{
TInt32bit iDiv= (TInt32bit)iValue;
long size= m_Digits.size();
for (long i=0;i<size-1;++ i)
{
m_Digits[i+1]+=(m_Digits[i]%iDiv)* emBase;
m_Digits[i]/= iDiv;
}
if (size>=1 )
m_Digits[size-1]/= iDiv;
}
else
{
TMaxInt iDiv= iValue;
long size= m_Digits.size();
TMaxInt cur_value=m_Digits[0 ];
for (long i=0;i<size-1;++ i)
{
m_Digits[i]=(TInt32bit)(cur_value/ iDiv);
cur_value=m_Digits[i+1]+(cur_value%iDiv)* emBase;
}
if (size>=1 )
m_Digits[size-1]=(TInt32bit)(cur_value/ iDiv);
}
Canonicity();
}
TLargeFloat::SelfType& TLargeFloat::operator /= (long double fValue)
{
TMaxInt iValue= (TMaxInt)fValue;
if (iValue== fValue)
{
DivInt(iValue);
return *this ;
}
else
return (*this)/= TLargeFloat(fValue);
}
TLargeFloat::SelfType& TLargeFloat::operator /= (const SelfType& Value)
{
SelfType x(Value);
x.Rev();//x=1/x;
return (*this)*= x;
}
void TLargeFloat::Rev()//求倒数
{
// 求1/a,
// 则有a=1/x; y=a-1/x;
// 求导得y'=1/x^2;
// 代入牛顿方程 x(n+1)=x(n)-y(x(n))/y'(x(n));
// 有迭代式 x_next=(2-a*x)*x; // 可证明:该公式为2阶收敛公式
// 证明:令x=1/a+dx;
// 则有x_next-1/a=(2-a*(1/a+dx))*(1/a+dx)-1/a
// =(-a)*dx^2
// 证毕.
if (this->m_Sign==0) throw TException("ERROR:TLargeFloat::Rev()" );
TExpInt oldExponent= m_Exponent;
SelfType a(*this );
a.m_Exponent=0 ;
SelfType x(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
x=1.0/a.AsFloat();//初始迭代值
TDigitsLengthAutoCtrl dlCtrl( 2,emLongDoubleDigits-1,(a.m_Digits.size()* TLargeFloat::em10Power));
SelfType ta(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
SelfType temp(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
dlCtrl.add_to_ctrl(& ta);
dlCtrl.add_to_ctrl(& x);
dlCtrl.add_to_ctrl(& temp);
for (long i=0;i<dlCtrl.get_runcount();++ i)
{
ta= a;
dlCtrl.SetNextDigits();
//x=x*2-x*x*ta;
temp= x;
temp*= temp;
temp*= ta;
x*=2 ;
x-= temp;
}
x.m_Exponent-= oldExponent;
this-> Swap(x);
}
/////
//
void TLargeFloat::RevSqrt() //
{
// 求1/a^0.5,
// 则有a=1/x^2; y=a-1/x^2;
// 求导得y'=2/x^3;
// 代入牛顿方程 x(n+1)=x(n)-y(x(n))/y'(x(n));
// 有迭代式 x_next=(3-a*x*x)*x/2; // 可证明:该公式为2阶收敛公式
// 证明:令x=1/a^0.5+dx;
// 则有x_next-1/a^0.5=(3-a*(1/a^0.5+dx)*(1/a^0.5+dx))*(1/a^0.5+dx)/2 - 1/a^0.5
// =-(1.5/a^0.5)*dx^2-0.5*a*dx^3;
// 证毕.
if (this->m_Sign<0) throw TException("ERROR:TLargeFloat::RevSqrt()" );
if (this->m_Sign==0) return ;
SelfType a(*this );
TMaxInt sqrExponent=a.m_Exponent.AsInt()/2 ;
a.m_Exponent-=(sqrExponent*2 );
SelfType x(0.0 ,TDigits(a.GetDigitsLength()));
x=1.0/sqrt(a.AsFloat());//初始迭代值
TDigitsLengthAutoCtrl dlCtrl( 2,emLongDoubleDigits-1,(a.m_Digits.size()* TLargeFloat::em10Power));
SelfType ta(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
SelfType temp(0.0 ,TLargeFloat::TDigits(a.GetDigitsLength()));
dlCtrl.add_to_ctrl(& ta);
dlCtrl.add_to_ctrl(& x);
dlCtrl.add_to_ctrl(& temp);
for (long i=0;i<dlCtrl.get_runcount();++ i)
{
ta= a;
dlCtrl.SetNextDigits();
//x=(3-x*x*ta)*x/2;
temp= x;
temp*= temp;
temp*= ta;
temp.Chs();
temp+=3 ;
x*= temp;
x/=2 ;
}
x.m_Exponent-= sqrExponent;
this-> Swap(x);
}
////
//*
void TLargeFloat::MulInt(TMaxInt iValue)
{
if (this->m_Sign==0) return ;
if (iValue==0 )
{
this-> Zero();
return ;
}
else if (iValue<0 )
{
iValue=- iValue;
this-> Chs();
//continue
}
if (iValue> csMaxMuliValue)
{
TLargeFloat y(0.0 );
y.iToLargeFloat(iValue);
(*this)*= y;
return ;
}
//乘以一个整数
TInt32bit Value= (TInt32bit)iValue;
long size= m_Digits.size();
for (long i=size-1;i>=0;-- i)
{
m_Digits[i]*= Value;
}
for (long j=size-1;j>=1;-- j)
{
if (m_Digits[j]>= emBase)
{
m_Digits[j-1]+=m_Digits[j]/ emBase;
m_Digits[j]%= emBase;
}
}
Canonicity();
}
TLargeFloat::SelfType& TLargeFloat::operator *= (long double fValue)
{
TMaxInt iValue= (TMaxInt)fValue;
if (iValue== fValue)
{
MulInt(iValue);
return *this ;
}
else
{
TLargeFloat temp(fValue);
return (*this)*= temp;
}
}
inline void getBestMulSize(const TInt32bit*& x,long& xsize,const TInt32bit*& y,long& ysize)
{
long bxsize= xsize;
long bysize= ysize;
long i;
for (i=xsize-1;i>=0;-- i)
{
if (x[i]==0 )
-- bxsize;
else
break ;
}
for (i=ysize-1;i>=0;-- i)
{
if (y[i]==0 )
-- bysize;
else
break ;
}
if (bxsize< bysize)
{
std::swap(bxsize,bysize);
std::swap(xsize,ysize);
std::swap(x,y);
}
xsize= bxsize;
const long csABigMulSize=1000 ;
if ( (bysize<csABigMulSize)||(bxsize*2>=bysize*3)||(bxsize> ysize) )
ysize= bysize;
else
ysize= bxsize;
}
TLargeFloat::SelfType& TLargeFloat::operator *= (const SelfType& Value)
{
long xsize= m_Digits.size();
long ysize= Value.m_Digits.size();
if ((m_Sign==0)||(Value.m_Sign==0 ))
{
if (m_Sign!=0 )
this-> Zero();
if (xsize< ysize)
m_Digits.resize(ysize,0 );
return *this ;
}
if (xsize< ysize)
m_Digits.resize(ysize,0 );
long rminsize=std::max(xsize,ysize)+2;//乘法结果需要的位数
const TInt32bit* x=&m_Digits[0 ];
const TInt32bit* y=&Value.m_Digits[0 ];
getBestMulSize(x,xsize,y,ysize);
if (rminsize>xsize+ ysize)
rminsize=xsize+ ysize;
TArray tempArray(rminsize);
ArrayMUL(&tempArray[0 ],rminsize,x,xsize,y,ysize);
xsize= m_Digits.size();
long resultsize= std::min(xsize,rminsize);
long i;
for (i=0;i<resultsize;++i) this->m_Digits[i]= tempArray[i];
for (i=resultsize;i<xsize;++i) this->m_Digits[i]=0 ;
m_Exponent+= Value.m_Exponent;
m_Sign*= Value.m_Sign;
Canonicity();
return *this ;
}
// 快速傅立叶变换实现大整数乘法
// FFT Mul
struct TComplex //复数类型
{
double i;
double r;
};
//初始化
void FFTInitial(TComplex* w,long* lst,const long n)
{
//计算W^i , i in [0--n)
const double PI=3.1415926535897932385 ;
const double seta=2.0*PI/ n;
long i,j;
long n2=n>>2 ;
for (i=0;i<=n2;++ i)
{
w[i].i=sin(seta* i);
w[i].r=cos(seta* i);
}
for (j=(n2+1),i=(n2-1); i>=0 ;--i,++ j)
{
w[j].i= w[i].i;
w[j].r=- w[i].r;
}
//计算排序用数组
lst[0]=0 ;
i=1 ;
long m;
for (n2=n>>1,m=2; n2>0 ;n2=n2>>1,m =m<<1 )
{
for (long j=0;i<m;++i,++ j)
{
lst[i]=lst[j]+ n2;
}
}
}
//快速傅立叶变换
void FFT(TComplex* a,const TComplex* w,const long n)
{
long n2=1 ;
long n1=n >> 1 ;
for (long per=1;per< n;)
{
long m=n2; long j=0; long k= n2;
per<<=1 ;
while (k< n)
{
for (long i2=0; j<m ;++j,++k,i2+= n1)
{
TComplex tmpb= a[j];
double tmp1=a[k].r*w[i2].r-a[k].i* w[i2].i;
double tmp2=a[k].r*w[i2].i+a[k].i* w[i2].r;
a[j].r=tmpb.r+ tmp1;
a[j].i=tmpb.i+ tmp2;
a[k].r=tmpb.r- tmp1;
a[k].i=tmpb.i- tmp2;
}
m+= per;
j+= n2;
k+= n2;
}
n2= per;
n1>>=1 ;
}
}
//反向快速傅立叶变换
void InvFFT(TComplex* a,const TComplex* w,const long n)
{
for (long i=0;i<n;++ i)
a[i].i=- a[i].i;
FFT(a,w,n);
}
void FFT_Convolution(const TComplex* a,TComplex* b,const long n)
{
for (long i=0;i<n;++ i)
{
double br=a[i].r*b[i].r - a[i].i* b[i].i;
b[i].i=a[i].r*b[i].i + a[i].i* b[i].r;
b[i].r= br;
}
}
void FFT_IntArrayCopyToComplexArray(const TInt32bit* ACoef,const long ASize,TComplex* result,const long n,const long* lst)
{
for (long i=0;i<n;++ i)
{
long ai= lst[i];
if (ai< ASize)
result[i].r= ACoef[ai];
else
result[i].r =0.0 ;
result[i].i=0.0 ;
}
}
void FFT_ComplexArrayToIntArray(const TComplex* cmx,const long n,TInt32bit* result,const long rMinSize)
{
const double tmpRevN=1.0/ n;
double FFT_int_base;
TLargeFloat::TArray tempResult;
TInt32bit* dst=0 ;
long dstsize=0 ;
{
FFT_int_base=(long )TLargeFloat::emBase;
dstsize= rMinSize;
dst= result;
}
const double tmpRevFFT_int_base=1.0/ FFT_int_base;
double MaxWorstEr=0 ;
double tmp=0.0 ;
for (long i=std::min(n,dstsize)-1;i>=1;-- i)
{
double num =cmx[i-1].r*tmpRevN+ tmp;
tmp=floor((num+0.499)* tmpRevFFT_int_base);
dst[i]=(TInt32bit)(num+0.499-tmp* FFT_int_base);
double newWorstEr=abs(num-tmp*FFT_int_base-dst[i]);//记录最大误差
if (newWorstEr> MaxWorstEr)
MaxWorstEr= newWorstEr;
}
if (dstsize>0 )
dst[0]=(TInt32bit)(tmp+0.1 );
if (MaxWorstEr>=0.499 )
throw TLargeFloat::TException("ERROR:FFT's FFT_ComplexArrayToIntArray(); "); //误差过大
}
//FFT平方
void SquareFFT(const TInt32bit* ACoef,const long ASize,TInt32bit* CCoef,const long CMinSize)
{
long ansize=ASize+ ASize;
long n=1 ;
while (n<ansize) n<<=1 ;
std::vector<TComplex> _w((n>>1)+1 );
std::vector<long> _lst(n);
TComplex* w=&_w[0 ];
long* lst=&_lst[0 ];
FFTInitial(w,lst,n);
std::vector<TComplex> _a(n);
TComplex* a=&_a[0 ];
FFT_IntArrayCopyToComplexArray(ACoef,ASize,a,n,lst);
FFT(a,w, n);
FFT_Convolution(a,a,n);
std::vector<TComplex> _tmpa(n);
_tmpa.swap(_a);
TComplex* tmpa=&_tmpa[0]; a=&_a[0 ];
for (long i=0;i<n;++i) a[i]= tmpa[lst[i]];
_tmpa.clear();
_lst.clear();
InvFFT(a,w,n);
_w.clear();
FFT_ComplexArrayToIntArray(a,n,CCoef,CMinSize);
}
//FFT乘法
void MulFFT(const TInt32bit* ACoef,const long ASize,const TInt32bit* BCoef,const long BSize,TInt32bit* CCoef,const long CMinSize)
{
long absize=(ASize+ BSize);
long n=1 ;
while (n<absize) n<<=1 ;
std::vector<TComplex> _w((n>>1)+1 );
std::vector<long> _lst(n);
TComplex* w=&_w[0 ];
long* lst=&_lst[0 ];
FFTInitial(w,lst,n);
std::vector<TComplex> _a(n);
TComplex* a=&_a[0 ];
FFT_IntArrayCopyToComplexArray(ACoef,ASize,a,n,lst);
std::vector<TComplex> _b(n);
TComplex* b=&_b[0 ];
FFT_IntArrayCopyToComplexArray(BCoef,BSize,b,n,lst);
FFT(b,w, n);
FFT(a,w, n);
FFT_Convolution(a,b,n);
for (long i=0;i<n;++i) a[i]= b[lst[i]];
_b.clear();
_lst.clear();
InvFFT(a,w,n);
_w.clear();
FFT_ComplexArrayToIntArray(a,n,CCoef,CMinSize);
}
/
const long csBestMUL_ExE_size =1024 / TLargeFloat::em10Power;
const long csBestMUL_Dichotomy_size =4096 / TLargeFloat::em10Power;
const long csBestMul_FFT4Max_size =16777216 / TLargeFloat::em10Power;
void ArrayMUL(TInt32bit* result,long rminsize,const TInt32bit* x,long xsize,const TInt32bit* y,long ysize)
{
if (xsize< ysize)
{
std::swap(xsize,ysize);
std::swap(x,y);
}
if (rminsize< ysize)
{
xsize= rminsize;
ysize= rminsize;
}
if (ysize<=csBestMUL_ExE_size) //
TLargeFloat_ArrayMUL_ExE(result,rminsize,x,xsize,y,ysize);
else if (ysize<= csBestMUL_Dichotomy_size)
ArrayMUL_DichotomyPart(result,rminsize,x,xsize,y,ysize);
else if ((xsize+ysize)<=(csBestMul_FFT4Max_size*2 ))
{
if (x== y)
SquareFFT(x,xsize,result,rminsize);
else
MulFFT(x,xsize,y,ysize,result,rminsize);
}
else
ArrayMUL_DichotomyPart(result,rminsize,x,xsize,y,ysize);
}
void LargeFloat_UnitTest()
{
// 单元测试
// 测试先行... 但作者太懒...
//todo:
TLargeFloat x( 200,TLargeFloat::TDigits(100 ));
TLargeFloat y(12345.678987654321,TLargeFloat::TDigits(100 ));
//TLargeFloat z("-12345.678987654321e-100",TLargeFloat::TDigits(100));
TLargeFloat z( "99999999999999999999999999999999999999999999",TLargeFloat::TDigits(200 ));
//
}
main函数,Demo程序
///
// LargeFloat.cpp
//
#include <iostream>
#include "TLargeFloat.h"
//#define _MY_TIME_CLOCK
#ifdef _MY_TIME_CLOCK
#include <windows.h>
#define clock_t __int64
clock_t CLOCKS_PER_SEC =0 ;
inline clock_t clock()
{
__int64 result;
if (CLOCKS_PER_SEC==0 )
{
QueryPerformanceFrequency((LARGE_INTEGER *)& result);
CLOCKS_PER_SEC= (clock_t)result;
}
QueryPerformanceCounter((LARGE_INTEGER *)& result);
return (clock_t)result;
}
#else
#include <time.h>
#endif
//计算圆周率PI
TLargeFloat GetBorweinPI(unsigned long uiDigitsLength);
TLargeFloat GetAGMPI(unsigned long uiDigitsLength);
TLargeFloat GetChudnovskyPI(unsigned long uiDigitsLength);
void Debug_toCout(const std::string& strx,const TLargeFloat& x)//调试输出
{ std::cout<<strx<<std::endl<<x<< std::endl; }
int main()
{
try
{
LargeFloat_UnitTest();
TLargeFloat x( 0.0,TLargeFloat::TDigits(100 ));
x=1 ;
Debug_toCout("1/7:=",x/7 );
x.StrToLargeFloat("12345678987654321" );
Debug_toCout("12345678987654321*12345678987654321 := ",x* x);
x=2 ;
Debug_toCout("2^0.5 := " ,sqrt(x));
//test PI
std::cout<<std::endl<<"请输入需要PI的有效位数:" ;
long pi_length=0; std::cin>>pi_length; std::cout<< std::endl;
clock_t t0= clock();
x=GetAGMPI(pi_length); //
//x=GetBorweinPI(pi_length)
t0=clock()- t0;
Debug_toCout("PI := " ,x);
std::cout<<"PI计算时间:"<<(t0*1.0/CLOCKS_PER_SEC)<<" 秒" ;
}
catch (const TLargeFloatException& lfe)
{
std::cout<<">> LargeFloat运算时发生异常: "<<lfe.what()<< std::endl;
}
catch (const std::exception& e)
{
std::cout<<">> 异常: "<<e.what()<< std::endl;
}
catch (...)
{
std::cout<<">> 未知的异常! "<< std::endl;
}
std::cout<< std::endl;
std::cout<<"...end..."<< std::endl;
char c; std::cin>> c;
return 0 ;
}
//计算圆周率PI
TLargeFloat GetBorweinPI(unsigned long uiDigitsLength)
{
// Borwein四次迭代式:
// 初值: a0=6-4*2^0.5; y0=2^0.5-1;
// 重复计算: y(n+1)=[1-(1-y^4)^0.25]/[1+(1-y^4)^0.25];
// y=y(n+1);
// a(n+1)=a*(1+y)^4-2^(2*n+3)*y*(1+y+y*y);
// 最后计算: PI=1/a;
// 迭代次数和10进制有效精度 每迭代一次有效精度增长4倍
// 0 1 2 3 4 5 6 ...
//0 8 40 170 693 2789 11171 ...
long loop_count;
if (uiDigitsLength<=8 )
loop_count=1 ;
else if (uiDigitsLength<=40 )
loop_count=2 ;
else if (uiDigitsLength<=170 )
loop_count=3 ;
else if (uiDigitsLength<=693 )
loop_count=4 ;
else if (uiDigitsLength<=2789 )
loop_count=5 ;
else
{
loop_count=6 ;
long DigitsLength=11171 ;
while (DigitsLength<(long )uiDigitsLength)
{
DigitsLength*=4;//四阶收敛
++ loop_count;
}
}
std::cout<<" ... 开始计算PI,Borwein四次迭代式, 总循环次数:"<<loop_count<<" ... "<< std::endl;
TLargeFloat::TDigits sCount(uiDigitsLength);//计算采用的十进制精度
TLargeFloat a( 0.0,sCount),y(0.0 ,sCount);
TLargeFloat temp(0.0 ,sCount);
TLargeFloat pow(2*2*2,sCount); // 2^(2*n+3); (n=0);
//a0=6-4*2^0.5;
temp=2 ;
temp.Sqrt();
a=6-4* temp;
//y0=2^0.5-1;
y=temp-1 ;
TLargeFloat tmpa(0.0 ,sCount);
for (long i=0;i<loop_count;++ i)
{
std::cout<<" ... 计算PI "<<uiDigitsLength<<" 位的当前循环次数:"<<i+1<<"/"<<loop_count<<" ... "<< std::endl;
temp=1- sqr(sqr(y));
temp=revsqrt(revsqrt(temp));//等价于 temp=sqrt(sqrt(temp));
y=(1-temp)/(1+ temp);
temp=sqr(1+ y);
a=a*sqr(temp)-pow*y*(temp- y);
pow*=4 ;
}
std::cout<<" ... 计算PI的循环结束,准备输出 ... "<< std::endl;
return 1/a;//PI=1/a;
}
TLargeFloat GetAGMPI(unsigned long uiDigitsLength)
{
// AGM二次迭代式:
// 初值:a=x=1 b=1/sqrt(2) c=1/4
// 重复计算:y=a a=(a+b)/2 b=sqrt(by) c=c-x(a-y)^2 x=2x
// 最后:pi=(a+b)^2/(4c)
// 迭代次数和10进制有效精度 每迭代一次有效精度增长2倍
// 0 1 2 3 4 5 6 7 8 ...
//1 39 82 169 344 693 1391 2788 5582 ...
long loop_count;
if (uiDigitsLength<=39 )
loop_count=1 ;
else if (uiDigitsLength<=82 )
loop_count=2 ;
else if (uiDigitsLength<=169 )
loop_count=3 ;
else if (uiDigitsLength<=344 )
loop_count=4 ;
else if (uiDigitsLength<=693 )
loop_count=5 ;
else if (uiDigitsLength<=1391 )
loop_count=6 ;
else if (uiDigitsLength<=2788 )
loop_count=7 ;
else
{
loop_count=8 ;
long DigitsLength=5582 ;
while (DigitsLength<(long )uiDigitsLength)
{
DigitsLength*=2;//2阶收敛
++ loop_count;
}
}
std::cout<<" ... 开始计算PI,AGM二次迭代式, 总循环次数:"<<loop_count<<" ... "<< std::endl;
TLargeFloat::TDigits sCount(uiDigitsLength);//计算采用的十进制精度
TLargeFloat c( 8,sCount); c.RevSqrt(); c.Chs(); //c=-sqrt(1/8);
TLargeFloat a(c); a*=(-3); a+=1; //a=1-3*c;
TLargeFloat b(a); b.Sqrt(); //b=sqrt(a);
TLargeFloat e("-0.625"); e += b; //e=b-0.625
b *= 2 ;
c += e;
a += e;
long npow=4 ;
for (long i=0;i<loop_count;++ i)
{
std::cout<<" ... 计算PI "<<uiDigitsLength<<" 位的当前循环次数:"<<i+1<<"/"<<loop_count<<" ... "<< std::endl;
e = a;
e += b;
e /= 2 ;
b *= a;
b.Sqrt();
e -= b;
b *= 2 ;
c -= e;
a = e;
a += b;
npow *= 2 ;
}
std::cout<<" ... 计算PI的循环结束,准备输出 ... "<< std::endl;
e *= e;
e /= 4 ;
a += b;
c *= a;
c -= e;
c *= npow;
a *= a;
a-= e;
e/=2 ;
a-= e;
a/= c;
return a;
}
//
///
// LargeFloat.cpp
//
#include <iostream>
#include "TLargeFloat.h"
//#define _MY_TIME_CLOCK
#ifdef _MY_TIME_CLOCK
#include <windows.h>
#define clock_t __int64
clock_t CLOCKS_PER_SEC =0 ;
inline clock_t clock()
{
__int64 result;
if (CLOCKS_PER_SEC==0 )
{
QueryPerformanceFrequency((LARGE_INTEGER *)& result);
CLOCKS_PER_SEC= (clock_t)result;
}
QueryPerformanceCounter((LARGE_INTEGER *)& result);
return (clock_t)result;
}
#else
#include <time.h>
#endif
//计算圆周率PI
TLargeFloat GetBorweinPI(unsigned long uiDigitsLength);
TLargeFloat GetAGMPI(unsigned long uiDigitsLength);
TLargeFloat GetChudnovskyPI(unsigned long uiDigitsLength);
void Debug_toCout(const std::string& strx,const TLargeFloat& x)//调试输出
{ std::cout<<strx<<std::endl<<x<< std::endl; }
int main()
{
try
{
LargeFloat_UnitTest();
TLargeFloat x( 0.0,TLargeFloat::TDigits(100 ));
x=1 ;
Debug_toCout("1/7:=",x/7 );
x.StrToLargeFloat("12345678987654321" );
Debug_toCout("12345678987654321*12345678987654321 := ",x* x);
x=2 ;
Debug_toCout("2^0.5 := " ,sqrt(x));
//test PI
std::cout<<std::endl<<"请输入需要PI的有效位数:" ;
long pi_length=0; std::cin>>pi_length; std::cout<< std::endl;
clock_t t0= clock();
x=GetAGMPI(pi_length); //
//x=GetBorweinPI(pi_length)
t0=clock()- t0;
Debug_toCout("PI := " ,x);
std::cout<<"PI计算时间:"<<(t0*1.0/CLOCKS_PER_SEC)<<" 秒" ;
}
catch (const TLargeFloatException& lfe)
{
std::cout<<">> LargeFloat运算时发生异常: "<<lfe.what()<< std::endl;
}
catch (const std::exception& e)
{
std::cout<<">> 异常: "<<e.what()<< std::endl;
}
catch (...)
{
std::cout<<">> 未知的异常! "<< std::endl;
}
std::cout<< std::endl;
std::cout<<"...end..."<< std::endl;
char c; std::cin>> c;
return 0 ;
}
//计算圆周率PI
TLargeFloat GetBorweinPI(unsigned long uiDigitsLength)
{
// Borwein四次迭代式:
// 初值: a0=6-4*2^0.5; y0=2^0.5-1;
// 重复计算: y(n+1)=[1-(1-y^4)^0.25]/[1+(1-y^4)^0.25];
// y=y(n+1);
// a(n+1)=a*(1+y)^4-2^(2*n+3)*y*(1+y+y*y);
// 最后计算: PI=1/a;
// 迭代次数和10进制有效精度 每迭代一次有效精度增长4倍
// 0 1 2 3 4 5 6 ...
//0 8 40 170 693 2789 11171 ...
long loop_count;
if (uiDigitsLength<=8 )
loop_count=1 ;
else if (uiDigitsLength<=40 )
loop_count=2 ;
else if (uiDigitsLength<=170 )
loop_count=3 ;
else if (uiDigitsLength<=693 )
loop_count=4 ;
else if (uiDigitsLength<=2789 )
loop_count=5 ;
else
{
loop_count=6 ;
long DigitsLength=11171 ;
while (DigitsLength<(long )uiDigitsLength)
{
DigitsLength*=4;//四阶收敛
++ loop_count;
}
}
std::cout<<" ... 开始计算PI,Borwein四次迭代式, 总循环次数:"<<loop_count<<" ... "<< std::endl;
TLargeFloat::TDigits sCount(uiDigitsLength);//计算采用的十进制精度
TLargeFloat a( 0.0,sCount),y(0.0 ,sCount);
TLargeFloat temp(0.0 ,sCount);
TLargeFloat pow(2*2*2,sCount); // 2^(2*n+3); (n=0);
//a0=6-4*2^0.5;
temp=2 ;
temp.Sqrt();
a=6-4* temp;
//y0=2^0.5-1;
y=temp-1 ;
TLargeFloat tmpa(0.0 ,sCount);
for (long i=0;i<loop_count;++ i)
{
std::cout<<" ... 计算PI "<<uiDigitsLength<<" 位的当前循环次数:"<<i+1<<"/"<<loop_count<<" ... "<< std::endl;
temp=1- sqr(sqr(y));
temp=revsqrt(revsqrt(temp));//等价于 temp=sqrt(sqrt(temp));
y=(1-temp)/(1+ temp);
temp=sqr(1+ y);
a=a*sqr(temp)-pow*y*(temp- y);
pow*=4 ;
}
std::cout<<" ... 计算PI的循环结束,准备输出 ... "<< std::endl;
return 1/a;//PI=1/a;
}
TLargeFloat GetAGMPI(unsigned long uiDigitsLength)
{
// AGM二次迭代式:
// 初值:a=x=1 b=1/sqrt(2) c=1/4
// 重复计算:y=a a=(a+b)/2 b=sqrt(by) c=c-x(a-y)^2 x=2x
// 最后:pi=(a+b)^2/(4c)
// 迭代次数和10进制有效精度 每迭代一次有效精度增长2倍
// 0 1 2 3 4 5 6 7 8 ...
//1 39 82 169 344 693 1391 2788 5582 ...
long loop_count;
if (uiDigitsLength<=39 )
loop_count=1 ;
else if (uiDigitsLength<=82 )
loop_count=2 ;
else if (uiDigitsLength<=169 )
loop_count=3 ;
else if (uiDigitsLength<=344 )
loop_count=4 ;
else if (uiDigitsLength<=693 )
loop_count=5 ;
else if (uiDigitsLength<=1391 )
loop_count=6 ;
else if (uiDigitsLength<=2788 )
loop_count=7 ;
else
{
loop_count=8 ;
long DigitsLength=5582 ;
while (DigitsLength<(long )uiDigitsLength)
{
DigitsLength*=2;//2阶收敛
++ loop_count;
}
}
std::cout<<" ... 开始计算PI,AGM二次迭代式, 总循环次数:"<<loop_count<<" ... "<< std::endl;
TLargeFloat::TDigits sCount(uiDigitsLength);//计算采用的十进制精度
TLargeFloat c( 8,sCount); c.RevSqrt(); c.Chs(); //c=-sqrt(1/8);
TLargeFloat a(c); a*=(-3); a+=1; //a=1-3*c;
TLargeFloat b(a); b.Sqrt(); //b=sqrt(a);
TLargeFloat e("-0.625"); e += b; //e=b-0.625
b *= 2 ;
c += e;
a += e;
long npow=4 ;
for (long i=0;i<loop_count;++ i)
{
std::cout<<" ... 计算PI "<<uiDigitsLength<<" 位的当前循环次数:"<<i+1<<"/"<<loop_count<<" ... "<< std::endl;
e = a;
e += b;
e /= 2 ;
b *= a;
b.Sqrt();
e -= b;
b *= 2 ;
c -= e;
a = e;
a += b;
npow *= 2 ;
}
std::cout<<" ... 计算PI的循环结束,准备输出 ... "<< std::endl;
e *= e;
e /= 4 ;
a += b;
c *= a;
c -= e;
c *= npow;
a *= a;
a-= e;
e/=2 ;
a-= e;
a/= c;
return a;
}
//
///