/*- ==========================================================
* 文件名 :MathFunc.h
* 開發人員:袁培榮
* 當前版本:1.3.3.2595 (第1次發佈,功能不斷增長中)
* 建立時間:2012-05-28
* 修改時間:2012-05-30
* 功能說明:加強的數學函數庫的聲明
* 版權說明:版權全部 袁培榮 YuanPeirong
* 編譯環境:Windows 7(x64) SP1 簡體中文專業版
* 編譯器: Visual Studio 2010 SP1(中文旗艦版)
MinGW 20120426 GNU GCC 4.6.2
Visual C++ 6.0 SP6(中文企業版)
- ==========================================================*/
//編譯測試狀況:
// 1.Visual Studio 2010 SP1(中文旗艦版):
// 在Release和Debug下都編譯經過,測試運行正常。
// 2.MinGW 20120426 GNU GCC 4.6.2:
// 編譯經過,測試運行正常。
// 3.Visual C++ 6.0 SP6(中文企業版)
// 未測試。
#ifndef MathFunc_H_TYCppStdLib //防止頭文件重複包含
#define MathFunc_H_TYCppStdLib
#ifdef MathFunc_DLL_API //爲導出DLL預留
#else
#define MathFunc_DLL_API _declspec(dllimport)
#endif
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector> //vector容器
#include <algorithm> //泛型算法
#include <numeric> //泛化算法
//#include <functional> //標準庫的函數對象類型在此定義
using namespace std;
namespace TYCppStdLib //全部功能都封裝在命名空間TYCppStdLib中
{
//產生一個隨機整數
int Random(
int minValue=-32768, //設置數據的最大值(包含)
int maxValue=32767, //設置數據的最大值(包含)
bool isPrime=false //是否必需要返回質數
);
//產生隨機純小數
double Random(
double minValue=0, //設置數據的最小值(包含)
double maxValue=1, //設置數據的最大值(包含)
bool get0and1=false //指明是否能夠產生0和1
);
//產生一組隨機整數(此函數是之前寫的,將要被我棄用,由於使用了不安全的數組)
//建議使用功能更增強大的 RandomVecInt函數(在下文中定義)
bool Random(
int *data, //用於存放產生的整數的數組首地址
int num, //設置要產生的數據個數
int minValue=-32768, //設置數據的最小值(包含)
int maxValue=32767, //設置數據的最大值(包含)
bool different=false //設置數據是否要互不相同
);
//爲Random函數定義相應的類,方便生成函數對象做爲泛型算法的發生器
class Random_cls
{
private:
int minValue;
int maxValue;
bool isPrime;
public:
Random_cls(int min, int max, bool isp);
int operator()();
};
bool IsPrime(int n); //判斷質數
//獲取n之內(含n)的全部質數的個數
int GetPrime(int n);
//獲取n之內(含n)的全部質數,並返回質數的個數
int GetPrime(int n, vector<int> &vec);
//int GetPrime(int n, int *p); //數組版本,因不安全,不想支持
bool IsSquare(int n); //判斷徹底平方數
//求兩個數的最大公約數
int GetGCD(int m, int n);
//求一組數據的最大公約數(不安全,不推薦使用)
int GetGCD(const int *p, int count);
//或者是int GetGCD(const int p[], int count);
//求一組數據的最大公約數(安全,推薦使用)
int GetGCD(vector<int> &vec);
//求兩個數的最小公倍數
int GetLCM(int m, int n);
//求一組數據的最小公倍數(不安全,不推薦使用)
int GetLCM(const int *p, int count);
//或者是int GetLCM(const int p[], int count);
//求一組數據的最小公倍數(安全,推薦使用)
int GetLCM(vector<int> &vec);
int GetFactorial(int n); //求階乘(13之內)(非遞歸和遞歸方式實現)
//得到0到n的階乘結果(n超過13時設爲13)
//這裏不用到GetFactorial,由於效率過低
void FacVecInt(vector<int> &vec, int n);
int InversionData(int n); //求整數的逆序數,如6589返回9856
//如下用到 vector 的函數均可以寫相應的數組版本
//可是由於數組是不安全的東西,不想再支持數組
//獲取數字的位數
int DivideDigit(int n);
//獲取數字的各個位上的數值,並返回分離出的數字個數
int DivideDigit(
int n, //待求數字
vector<int> &vec, //存儲結果
bool forward=true //ture:高位在前存儲,false:低位在前存儲
);
//獲取數字的各個位上的數值(高位在前),並返回分離出的數字個數
//int DivideDigitA(int n, vector<int> &vec); //再也不須要
//獲取數字的各個位上的數值(低位在前),並返回分離出的數字個數
//int DivideDigitB(int n, vector<int> &vec); //再也不須要
//將一組數據按位合成一個數
int JoinDigit(
const vector<int> &vec, //一組數據
bool forward=true, //ture:高位在前,false:低位在前
bool onlyBit=false //數據中的每一位是否只取其個位
);
//生成一組隨機數據(用隨機數據初始化vector<int>)
void RandomVecInt(
vector<int> &vec, //存放數據的容器
int num, //產生數據的個數
int minValue=-32768, //設置數據的最大值(包含)
int maxValue=32767, //設置數據的最大值(包含)
bool isPrime=false //產生的數據是否必須爲質數
);
//求Fibonacci數列的第N項 F1=1 F2=1 F3=2 ……(非遞歸和遞歸方式實現)
int Fibonacci(int n);
//求Fibonacci數列的前N項(用Fibonacci數列初始化vector<int>)
//這裏不用到Fibonacci函數,由於效率過低
void FibVecInt(vector<int> &vec, int num);
//求一組數據的和
template<typename T>
T GetSum(const vector<T> &vec);
// template<typename T> //初始實現版本
// T GetSum(typename vector<T>::const_iterator start, typename vector<T>::const_iterator end);
//調用方式:T sum=GetSum(s, e)或者 GetSum<T>(s, e)
template<typename T, typename InputIterator> //更加泛化的實現版本
T GetSum(InputIterator start, InputIterator end);
//調用方式:T sum=GetSum(s, e)或者 GetSum<T>(s, e)
//求一組數據的算術平均數(涉及到除法,所以返回值轉爲double,下同)
template<typename T>
double GetMean(const vector<T> &vec);
//求一組數據的方差
template<typename T>
double GetVariance(const vector<T> &vec);
//求一組數據的標準差
template<typename T>
double GetStDev(const vector<T> &vec);
//將一組數據反序,並覆蓋原數據
template<typename T>
void InverseVec(vector<T> &vec); //結果覆蓋原數據
//將一組數據反序,不覆蓋原數據
template<typename T>
void InverseVec(
const vector<T> &vec1, //原數據
vector<T> &vec2 //逆序數據
);
//比較兩個數的大小
template<typename T>
bool IsBig(const T &m, const T &n);
template<typename T>
bool IsSmall(const T &m, const T &n);
//將一組數據進行排序,並覆蓋原數據
template<typename T>
void SortVec(
vector<T> &vec, //結果覆蓋原數據
bool smallToBig=true, //ture:從小到大,false:從大到小
bool eraseUnique=false //ture:去除重複值,false:不去除重複值
);
//將一組數據進行排序,不覆蓋原數據
template<typename T>
void SortVec(
const vector<T> &vec1, //原數據
vector<T> &vec2, //逆序數據
bool smallToBig=true, //ture:從小到大,false:從大到小
bool eraseUnique=false //ture:去除重複值,false:不去除重複值
);
//生成等差數列(Arithmetic Sequence)(用等差數列初始化vector<T>)
template<typename T>
void AriVecT(
vector<T> &vec, //存儲數據
T fisrt, //首項
T tolerance, //公差
T num //項數
);
//生成等比數列(Geometric Sequence)(用等比數列初始化vector<T>)
template<typename T>
void GeoVecT(
vector<T> &vec, //存儲數據
T fisrt, //首項
T comRatio, //公比
T num //項數
);
// 僅爲測試
// template<typename T>
// T GetTest(T n);
}
//爲了兼容各編譯器,特別是VC++6.0這種低級的舊版本編譯器
//只好採用模板的包含編譯模式
//模板的實現放在.hpp文件中,編譯時不單獨編譯
//而事實上, Visual Studio 2010也不能採用更先進的分離編譯模式
//而對C++標準支持得最好的MinGW也不能支持更先進的分離編譯模式
//除了國外極少數的冷門商業編譯器支持分離編譯模式
//我現有的編譯器都不僅支持,所以只能頭文件反向包含源文件的作法
//採用了boost的作法,將其反綴名定爲 .hpp ,即 .h + .cpp
#include "MathFunc.hpp"
//在編譯時,應將此hpp文件當作頭文件而非源文件,即不單獨編譯
#endif
//摘自:SGI STL
/* template<typename _InputIterator, typename _Tp>
inline _Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_requires_valid_range(__first, __last);
for (; __first != __last; ++__first)
__init = __init + *__first;
return __init;
} */
/*- ==========================================================
* 文件名 :MathFunc.cpp
* 開發人員:袁培榮
* 當前版本:1.3.3.2595 (第1次發佈,功能不斷增長中)
* 建立時間:2012-05-28
* 修改時間:2012-05-30
* 功能說明:加強的數學函數庫的實現
* 版權說明:版權全部 袁培榮 YuanPeirong
* 編譯環境:Windows 7(x64) SP1 簡體中文專業版
* 編譯器: Visual Studio 2010 SP1(中文旗艦版)
MinGW 20120426 GNU GCC 4.6.2
Visual C++ 6.0 SP6(中文企業版)
- ==========================================================*/
//編譯測試狀況:
// 1.Visual Studio 2010 SP1(中文旗艦版):
// 在Release和Debug下都編譯經過,測試運行正常。
// 2.MinGW 20120426 GNU GCC 4.6.2:
// 編譯經過,測試運行正常。
// 3.Visual C++ 6.0 SP6(中文企業版)
// 未測試。
#ifndef MathFunc_DLL_ForAPI
#define MathFunc_DLL_ForAPI
#define MathFunc_DLL_API _declspec(dllexport) //爲導出DLL預留
#endif
#include "../Include/MathFunc.h"
using namespace std;
using namespace TYCppStdLib;
//產生一個隨機整數
int TYCppStdLib::Random(
int minValue, //設置數據的最大值(包含)
int maxValue, //設置數據的最大值(包含)
bool isPrime //是否必需要返回質數
)
{
if(maxValue<minValue)
return 0;//return false;
if(minValue<-32768)
minValue=-32768;
if(maxValue>32767)
maxValue=32767;
int ix;
static bool randomFisrt=true;
if(randomFisrt)
srand(time(static_cast<time_t>(0)));
randomFisrt=false;
ix=rand();
ix=ix%(maxValue-minValue+1)+minValue;
if(!isPrime)
return ix;
bool isp=IsPrime(ix);
if(isp)
return ix;
while(!isp)
{
ix=rand();
ix=ix%(maxValue-minValue+1)+minValue;
isp=IsPrime(ix);
}
return ix;
}
//產生隨機純小數
double TYCppStdLib::Random(double minValue, double maxValue, bool get0and1)
{
if(maxValue<minValue)
return 0;//return false;
if(minValue<0)
minValue=0;
if(maxValue>1)
maxValue=1;
double dx;
int ix1, ix2;
ix1=(int)(minValue*32767);
ix2=(int)(maxValue*32767);
ix1=Random(ix1, ix2);
if(false==get0and1 && 0==minValue && 1==maxValue)
{
if(!ix1)
ix1=1;
if(ix1==32767)
ix1=32766;
}
dx=(double)(ix1)/32767;
return dx;
}
//產生一組隨機整數(此函數是之前寫的,將要被我棄用,由於使用了不安全的數組)
bool TYCppStdLib::Random(int *data, int num, int minValue, int maxValue, bool different)
{
if(num<1 || maxValue<minValue)
return false;
if(minValue<-32768)
minValue=-32768;
if(maxValue>32767)
maxValue=32767;
if(different && (maxValue-minValue+1)<num)
return false;
int ii, ij, ix;
for(ii=0;ii<num;ii++)
{
while(1)
{
ix=Random(minValue, maxValue);
if(!different)
break;
for(ij=0;ij<ii;ij++)
{
if(ix==*(data+ij))
break;
}
if(ij==ii)
break;
}
*(data+ii)=ix;
}
return true;
}
//如下的函數是正確的,只是將數組形參寫成指針形式更好,所以棄用
// 產生一批隨機整數
// bool Random(
// int data[], //用於存放產生的整數的數組
// int num, //設置要產生的數據個數
// int minValue=-32768, //設置數據的最小值(包含)
// int maxValue=32767,//設置數據的最大值(包含)
// bool different=false //設置數據是否要互不相同
// );
// bool Random(int data[], int num, int minValue, int maxValue, bool different)
// {
// if(num<1 || maxValue<minValue)
// return false;
// if(minValue<-32768)
// minValue=-32768;
// if(maxValue>32767)
// maxValue=32767;
// if(different && (maxValue-minValue+1)<num)
// return false;
// int ii, ij=0, ix;
// for(ii=0;ii<num;ii++)
// {
// while(1)
// {
// ix=Random(minValue, maxValue);
// if(!different)
// break;
// for(ij=0;ij<ii;ij++)
// {
// if(ix==data[ij])
// break;
// }
// if(ij==ii)
// break;
// }
// data[ii]=ix;
// }
// return true;
// }
//爲Random函數定義相應的類,方便生成函數對象做爲泛型算法的發生器
TYCppStdLib::Random_cls::Random_cls(int min, int max, bool isp)
{
minValue=min;
maxValue=max;
isPrime=isp;
}
int TYCppStdLib::Random_cls::operator()()
{
return Random(minValue, maxValue, isPrime);
}
//判斷質數
bool TYCppStdLib::IsPrime(int n)
{
n=abs(n); //容許n是負數
if(n<2)
return false;
int m=static_cast<int>(sqrt(static_cast<double>(n)))+1;
for(int i=2; i<m+1; i++) //i<m或i<m+1
if(n%i==0)
return false;
return true;
}
//獲取n之內(含n)的全部質數的個數
int TYCppStdLib::GetPrime(int n)
{
if(n<2)
return 0;
if(2==n)
return 1;
int num=1;
for(int i=3; i<=n; i=i+2)
if(IsPrime(i))
num++;
return num;
}
//獲取n之內(含n)的全部質數,並返回質數的個數
int TYCppStdLib::GetPrime(int n, vector<int> &vec)
{
vec.clear();
if(n<2)
return 0;
if(2==n)
{
vec.push_back(2);
return 1;
}
vec.push_back(2);
for(int i=3; i<=n; i=i+2)
if(IsPrime(i))
vec.push_back(i);
return static_cast<int>(vec.size());
}
//判斷徹底平方數
bool TYCppStdLib::IsSquare(int n)
{
if(n<0)
return false;
int m=static_cast<int>(sqrt(static_cast<double>(n)));
if(m*m==n)
return true;
return false;
}
//求兩個數的最大公約數
int TYCppStdLib::GetGCD(int m, int n)
{
if(!m && !n)
return 0;
if(!m)
return n;
if(!n)
return m;
int r;
while(r=m%n)
{
m=n;
n=r;
}
return abs(n);
}
//求一組數據的最大公約數(不安全,不推薦使用)
int TYCppStdLib::GetGCD(const int *p, int count)
{
if(!p || count<2)
return 0;
int gcd=p[0];
for(int i=1; i!=count; i++)
gcd=GetGCD(gcd,p[i]);
return abs(gcd);
}
//求一組數據的最大公約數(安全,推薦使用)
int TYCppStdLib::GetGCD(vector<int> &vec)
{
int vsize=vec.size();
if(vsize<2)
return 0;
int gcd=vec[0];
for(int i=1; i!=vsize; i++)
gcd=GetGCD(gcd, vec[i]);
return abs(gcd);
}
//求兩個數的最小公倍數
int TYCppStdLib::GetLCM(int m, int n)
{
if(!m || !n)
return 0;
int lcm=m*n/GetGCD(m, n); //GetGCD(m, n)不會再返回0
return abs(lcm); //由於返回0的狀況在前面已經排除
}
//求一組數據的最小公倍數(不安全,不推薦使用)
int TYCppStdLib::GetLCM(const int *p, int count)
{
if(!p || count<2)
return 0;
int lcm=p[0];
for(int i=1; i!=count; i++)
lcm=GetLCM(lcm, p[i]);
return abs(lcm);
}
//求一組數據的最小公倍數(安全,推薦使用)
int TYCppStdLib::GetLCM(vector<int> &vec)
{
int vsize=vec.size();
if(vsize<2)
return 0;
int lcm=vec[0];
for(int i=1; i!=vsize; i++)
lcm=GetLCM(lcm, vec[i]);
return abs(lcm);
}
//求階乘(13之內)(非遞歸)
int TYCppStdLib::GetFactorial(int n)
{
if(n<0 || n>13)
return 0;
if(n<2)
return 1;
int fac=1;
for(int i=2; i<=n; i++)
fac=fac*i;
return fac;
}
//如下爲求階乘的遞歸實現,兩種方法效率幾乎相同
//但爲減少函數重複調用開銷,選擇非遞歸方式
//求階乘(13之內)(遞歸)
// int TYCppStdLib::GetFactorial(int n)
// {
// if(n<0 || n>13)
// return 0;
// if(n<2)
// return 1;
// return GetFactorial(n-1)*n;
// }
//得到0到n的階乘結果(n超過13時設爲13)
//這裏不用到GetFactorial,由於效率過低
void TYCppStdLib::FacVecInt(vector<int> &vec, int n)
{
vec.clear();
if(n<0)
return;
vec.push_back(1);
if(0==n)
return;
vec.push_back(1);
if(1==n)
return;
if(n>13)
n=13;
int fac=1;
for(int i=1; i!=n; i++)
{
fac=fac*(i+1);
vec.push_back(fac);
}
}
//求整數的逆序數,如6589返回9856
int TYCppStdLib::InversionData(int n)
{
int s=0;
while(n)
{
s=10*s+n%10;
n=n/10;
}
return s;
}
//獲取數字的位數
int TYCppStdLib::DivideDigit(int n)
{
n=abs(n);
if(0==n)
return 1;
int num=0;
while(n)
{
n=n/10;
num++;
}
return num;
}
//獲取數字的各個位上的數值,並返回分離出的數字個數
int TYCppStdLib::DivideDigit(
int n, //待求數字
vector<int> &vec, //存儲結果
bool forward //ture:高位在前存儲,false:低位在前存儲
)
{
n=abs(n);
vec.clear();
int num=0;
if(0==n)
{
vec.push_back(0);
return 1;
}
if(forward)
{
while(n)
{
vec.insert(vec.begin(), n%10);
n=n/10;
num++;
}
}
else
{
while(n)
{
vec.push_back(n%10);
n=n/10;
num++;
}
}
return num;
}
//如下兩個函數的功能已經被集成到上面的函數中
//獲取數字的各個位上的數值(高位在前),並返回分離出的數字個數
// int TYCppStdLib::DivideDigitA(int n, vector<int> &vec)
// {
// n=abs(n);
// vec.clear();
// if(0==n)
// {
// vec.push_back(0);
// return 1;
// }
// int num=0;
// while(n)
// {
// vec.insert(vec.begin(), n%10);
// n=n/10;
// num++;
// }
// return num;
// }
//獲取數字的各個位上的數值(低位在前),並返回分離出的數字個數
// int TYCppStdLib::DivideDigitB(int n, vector<int> &vec)
// {
// n=abs(n);
// vec.clear();
// if(0==n)
// {
// vec.push_back(0);
// return 1;
// }
// int num=0;
// while(n)
// {
// vec.push_back(n%10);
// n=n/10;
// num++;
// }
// return num;
// }
//將一組數據按位合成一個數
int TYCppStdLib::JoinDigit(
const vector<int> &vec, //一組數據
bool forward, //ture:高位在前,false:低位在前
bool onlyBit //數據中的每一位是否只取其個位
)
{
if(vec.empty())
return 0;
int sum=0;
vector<int>::size_type si;
if(forward)
{
for(si=0; si!=vec.size(); si++)
{
if(onlyBit)
sum=sum*10+(vec[si]%10);
else
sum=sum*10+vec[si];
}
}
else
{
for(si=vec.size()-1; si!=-1; si--)
{
if(onlyBit)
sum=sum*10+(vec[si]%10);
else
sum=sum*10+vec[si];
}
}
return sum;
}
//生成一組隨機數據(用隨機數據初始化vector<int>)
void TYCppStdLib::RandomVecInt(
vector<int> &vec, //存放數據的容器
int num, //產生數據的個數
int minValue, //設置數據的最大值(包含)
int maxValue, //設置數據的最大值(包含)
bool isPrime //產生的數據是否必須爲質數
)
{
vec.clear();
if (num<1)
return;
vec.resize(num);
generate(vec.begin(), vec.end(),
Random_cls(minValue, maxValue, isPrime));
return;
}
//求Fibonacci數列的第N項 F1=1 F2=1 F3=2 ……(非遞歸)
int TYCppStdLib::Fibonacci(int n)
{
if(n<1)
return 0;
if(1==n || 2==n)
return 1;
int fib;
int n_1=1;
int n_2=1;
for(int i=2; i!=n; i++)
{
fib=n_1+n_2;
n_2=n_1;
n_1=fib;
}
return fib;
}
//如下爲求Fibonacci數列的第N項的遞歸實現,兩種方法效率幾乎相同
//但爲減少函數重複調用開銷,選擇非遞歸方式
//求Fibonacci數列的第N項 F1=1 F2=1 F3=2 ……(遞歸)
// int TYCppStdLib::Fibonacci(int n)
// {
// if(n<1)
// return 0;
// if(1==n || 2==n)
// return 1;
// return (Fibonacci(n-1)+Fibonacci(n-2));
// }
//求Fibonacci數列的前N項(用Fibonacci數列初始化vector<int>)
//這裏不用到Fibonacci函數,由於效率過低
void TYCppStdLib::FibVecInt(vector<int> &vec, int num)
{
vec.clear();
if(num<1)
return;
vec.push_back(1);
if(1==num)
return;
vec.push_back(1);
if(2==num)
return;
int n;
int n_1=1;
int n_2=1;
for(int i=2; i!=num; i++)
{
n=n_1+n_2;
vec.push_back(n);
n_2=n_1;
n_1=n;
}
}
// 僅爲測試
// template<typename T>
// T TYCppStdLib::GetTest(T n)
// {
// return (-n);
// }
/*- ==========================================================
* 文件名 :MathFunc.hpp
* 開發人員:袁培榮
* 當前版本:1.3.3.2595 (第1次發佈,功能不斷增長中)
* 建立時間:2012-05-28
* 修改時間:2012-05-30
* 功能說明:加強的數學函數庫的模板實現
* 版權說明:版權全部 袁培榮 YuanPeirong
* 編譯環境:Windows 7(x64) SP1 簡體中文專業版
* 編譯器: Visual Studio 2010 SP1(中文旗艦版)
MinGW 20120426 GNU GCC 4.6.2
Visual C++ 6.0 SP6(中文企業版)
- ==========================================================*/
//編譯測試狀況:
// 1.Visual Studio 2010 SP1(中文旗艦版):
// 在Release和Debug下都編譯經過,測試運行正常。
// 2.MinGW 20120426 GNU GCC 4.6.2:
// 編譯經過,測試運行正常。
// 3.Visual C++ 6.0 SP6(中文企業版)
// 未測試。
#ifndef MathFunc_HPP_TYCppStdLib //防止頭文件重複包含
#define MathFunc_HPP_TYCppStdLib
#include <iostream>
//求一組數據的和
//export template<typename T>
template<typename T>
T TYCppStdLib::GetSum(const vector<T> &vec)
{
T sum=accumulate(vec.begin(), vec.end(), static_cast<T>(0));
return sum;
}
//初始實現版本
// template<typename T>
// T TYCppStdLib::GetSum(
// typename vector<T>::const_iterator start
// , typename vector<T>::const_iterator end
// )
// {
// T sum=accumulate(start, end, static_cast<T>(0));
// return sum;
// }
//更加泛化的實現版本
template<typename T, typename InputIterator>
T TYCppStdLib::GetSum(InputIterator start, InputIterator end)
{
T sum=accumulate(start, end, static_cast<T>(0));
return sum;
}
//求一組數據的算術平均數(涉及到除法,所以返回值轉爲double,下同)
template<typename T>
double TYCppStdLib::GetMean(const vector<T> &vec)
{
int num=static_cast<int>(vec.size());
if(0==num)
return static_cast<double>(0);
T sum=accumulate(vec.begin(), vec.end(), static_cast<T>(0));
return (static_cast<double>(sum))/(static_cast<double>(num));
}
//求一組數據的方差(第1正確實現版本)
// template<typename T>
// double TYCppStdLib::GetVariance(const vector<T> &vec)
// {
// double mean=GetMean(vec);
// vector<double> temp;
// for(vector<double>::size_type si=0; si!=vec.size(); si++)
// { // vec爲空也不會出錯
// double vsi=static_cast<double>(vec[si]);
// temp.push_back((vsi-mean)*(vsi-mean));
// }
// return GetMean(temp);
// }
//求一組數據的方差(優化實現版本)
//===
//優化緣由:
// 1.避免構造臨時vector,
// 2.避免調用外部函數對臨時vector的遍歷
// 3.減小外部函數的調用次數
// 4.更快的處理空數據
// 5.減小內存佔用
//===
template<typename T>
double TYCppStdLib::GetVariance(const vector<T> &vec)
{
int num=static_cast<int>(vec.size());
if(0==num)
return static_cast<double>(0);
double mean=GetMean(vec);
double sum=0; //sum和平均數有關,而平均數已是double了
for(vector<double>::size_type si=0; si!=vec.size(); si++)
{
double vsi=static_cast<double>(vec[si]);
sum=sum+((vsi-mean)*(vsi-mean));
}
return sum/(static_cast<double>(num));
}
//求一組數據的標準差
template<typename T>
double TYCppStdLib::GetStDev(const vector<T> &vec)
{
return sqrt(GetVariance(vec));
}
//將一組數據反序,並覆蓋原數據
template<typename T>
void TYCppStdLib::InverseVec(vector<T> &vec) //結果覆蓋原數據
{
vector<T> vec2;
for(typename vector<T>::size_type si=0; si!=vec.size(); si++)
vec2.insert(vec2.begin(), vec[si]);
vec=vec2;
return;
}
//將一組數據反序,不覆蓋原數據
template<typename T>
void TYCppStdLib::InverseVec(
const vector<T> &vec1, //原數據
vector<T> &vec2 //逆序數據
)
{
vec2.clear();
for(typename vector<T>::size_type si=0; si!=vec1.size(); si++)
vec2.insert(vec2.begin(), vec1[si]);
return;
}
//比較兩個數的大小
template<typename T>
bool TYCppStdLib::IsBig(const T &m, const T &n)
{
return m>=n;
}
template<typename T>
bool TYCppStdLib::IsSmall(const T &m, const T &n)
{
return m<n;
}
//將一組數據進行排序,並覆蓋原數據
template<typename T>
void TYCppStdLib::SortVec(
vector<T> &vec, //結果覆蓋原數據
bool smallToBig, //ture:從小到大,false:從大到小
bool eraseUnique //ture:去除重複值,false:不去除重複值
)
{
if(smallToBig)
sort(vec.begin(), vec.end(), IsSmall<T>); //標準庫有less和less_equal
//也能夠寫成sort(vec.begin(), vec.end());
//但在MinGW和VS2010的Release下編譯經過,運行正常
//VS2010的Debug下編譯經過,運行錯誤
//但寫成sort(vec.begin(), vec.end(), IsSmall<T>);
//在MinGW和VS2010的Release,Debug下都編譯經過而運行正常
else
sort(vec.begin(), vec.end(), IsBig<T>); //標準庫有greater和greater_equal
if(eraseUnique)
{
typename vector<T>::iterator end_unique=
unique(vec.begin(), vec.end());
vec.erase(end_unique, vec.end());
}
}
//將一組數據進行排序,不覆蓋原數據
template<typename T>
void TYCppStdLib::SortVec(
const vector<T> &vec1, //原數據
vector<T> &vec2, //逆序數據
bool smallToBig, //ture:從小到大,false:從大到小
bool eraseUnique //ture:去除重複值,false:不去除重複值
)
{
vec2=vec1;
SortVec(vec2, smallToBig, eraseUnique);
}
//生成等差數列(Arithmetic Sequence)(用等差數列初始化vector<T>)
template<typename T>
void TYCppStdLib::AriVecT(
vector<T> &vec, //存儲數據
T fisrt, //首項
T tolerance, //公差
T num //項數
)
{
vec.clear();
if(num<1)
return;
for(int i=0; i!=num; i++)
{
vec.push_back(fisrt);
fisrt=fisrt+tolerance;
}
}
//生成等比數列(Geometric Sequence)(用等比數列初始化vector<T>)
template<typename T>
void TYCppStdLib::GeoVecT(
vector<T> &vec, //存儲數據
T fisrt, //首項
T comRatio, //公比
T num //項數
)
{
vec.clear();
if(num<1)
return;
for(int i=0; i!=num; i++)
{
vec.push_back(fisrt);
fisrt=fisrt*comRatio;
}
}
#endif
/*- ==========================================================
* 文件名 :test1.cpp
* 開發人員:袁培榮
* 當前版本:1.3.3.2595 (第1次發佈,功能不斷增長中)
* 建立時間:2012-05-28
* 修改時間:2012-05-30
* 功能說明:加強的數學函數庫的測試代碼
* 版權說明:版權全部 袁培榮 YuanPeirong
* 編譯環境:Windows 7(x64) SP1 簡體中文專業版
* 編譯器: Visual Studio 2010 SP1(中文旗艦版)
MinGW 20120426 GNU GCC 4.6.2
Visual C++ 6.0 SP6(中文企業版)
- ==========================================================*/
//編譯測試狀況:
// 1.Visual Studio 2010 SP1(中文旗艦版):
// 在Release和Debug下都編譯經過,測試運行正常。
// 2.MinGW 20120426 GNU GCC 4.6.2:
// 編譯經過,測試運行正常。
// 3.Visual C++ 6.0 SP6(中文企業版)
// 未測試。
#include <iostream>
#include "../Include/MathFunc.h"
//#include <vector> //MathFunc.h中已經包含此頭文件
using namespace std;
using namespace TYCppStdLib;
template<typename T> //僅爲方便輸出容器的每一項
void CoutVecT(const vector<T> &vec);
int main(int argc, char* argv[])
{
if(IsPrime(5))
cout<<"5是質數"<<endl;
else
cout<<"5不是質數"<<endl;
if(IsPrime(9))
cout<<"9是質數"<<endl;
else
cout<<"9不是質數"<<endl;
if(IsSquare(5))
cout<<"5是徹底平方數"<<endl;
else
cout<<"5不是徹底平方數"<<endl;
if(IsSquare(9))
cout<<"9是徹底平方數"<<endl;
else
cout<<"9不是徹底平方數"<<endl;
cout<<"27和18的最大公約數是:"<<GetGCD(27, 18)<<endl;
cout<<"27和18的最小公倍數是:"<<GetLCM(27, 18)<<endl;
int arr[5]={6,9,36,18,72};
cout<<"數組arr的最大公約數是:"<<GetGCD(arr, 5)<<endl;
cout<<"數組arr的最小公倍數是:"<<GetLCM(arr, 5)<<endl;
vector<int> v1;
v1.push_back(6);
v1.push_back(9);
v1.push_back(36);
v1.push_back(18);
v1.push_back(72);
cout<<"容器v1的最大公約數是:"<<GetGCD(v1)<<endl;
cout<<"容器v1的最小公倍數是:"<<GetLCM(v1)<<endl;
cout<<"-1的階乘是:"<<GetFactorial(-1)<<endl;
cout<<"0的階乘是:"<<GetFactorial(0)<<endl;
cout<<"1的階乘是:"<<GetFactorial(1)<<endl;
cout<<"2的階乘是:"<<GetFactorial(2)<<endl;
cout<<"5的階乘是:"<<GetFactorial(5)<<endl;
cout<<"13的階乘是:"<<GetFactorial(13)<<endl;
cout<<"15的階乘是:"<<GetFactorial(15)<<endl;
cout<<"0-15的階乘爲:"<<endl;
vector<int> fac(10);
FacVecInt(fac, 15);
CoutVecT(fac);
cout<<"-1234的逆序數是"<<InversionData(-1234)<<endl;
cout<<"-1的逆序數是"<<InversionData(-1)<<endl;
cout<<"0的逆序數是"<<InversionData(0)<<endl;
cout<<"1的逆序數是"<<InversionData(1)<<endl;
cout<<"1234的逆序數是"<<InversionData(1234)<<endl;
cout<<"123456的逆序數是"<<InversionData(123456)<<endl;
vector<int> v2(10);
int i=17;
cout<<GetPrime(i)<<endl;
cout<<i<<"之內有"<<GetPrime(i, v2)<<"個質數"<<endl;
CoutVecT(v2);
vector<int> v3(10,9);
vector<int> v4;
vector<int> v5;
v5.push_back(2); //2+4+6=12 平均4
v5.push_back(4); //方差 (4+0+4)/3
v5.push_back(6);
cout<<"v3和:"<<GetSum(v3)<<endl;
cout<<"v4和:"<<GetSum(v4)<<endl;
cout<<"v5和:"<<GetSum(v5)<<endl;
vector<int>::iterator is=v3.begin();
vector<int>::iterator ie=v3.end();
is++;
is++;
cout<<"v3後七項和:"<<GetSum<int>(is, ie)<<endl;
cout<<"v3平均:"<<GetMean(v3)<<endl;
cout<<"v4平均:"<<GetMean(v4)<<endl;
cout<<"v5平均:"<<GetMean(v5)<<endl;
cout<<"v3方差:"<<GetVariance(v3)<<endl;
cout<<"v4方差:"<<GetVariance(v4)<<endl;
cout<<"v5方差:"<<GetVariance(v5)<<endl;
cout<<"v3標準差:"<<GetStDev(v3)<<endl;
cout<<"v4標準差:"<<GetStDev(v4)<<endl;
cout<<"v5標準差:"<<GetStDev(v5)<<endl;
cout<<"數字分離"<<endl;
int i2=256;
vector<int> v6(10,1);
vector<int> v7(10,2);
cout<<DivideDigit(i2)<<endl;
cout<<DivideDigit(i2, v6)<<endl;
cout<<DivideDigit(i2, v7, false)<<endl;
CoutVecT(v6);
CoutVecT(v7);
cout<<"數字合成"<<endl;
vector<int> v8;
v8.push_back(15);
v8.push_back(16);
cout<<JoinDigit(v8,true, true)<<endl;
cout<<JoinDigit(v8,true, false)<<endl;
cout<<JoinDigit(v8,false, true)<<endl;
cout<<JoinDigit(v8,false, false)<<endl;
cout<<"數據反序"<<endl;
vector<int> v9;
v9.push_back(11);
v9.push_back(22);
v9.push_back(33);
InverseVec(v9);
CoutVecT(v9);
vector<int> v10;
v10.push_back(11);
v10.push_back(22);
v10.push_back(33);
vector<int> v11(20);
InverseVec(v10, v11);
CoutVecT(v10);
CoutVecT(v11);
cout<<"測試隨機數"<<endl;
for(int ii=0; ii<5; ii++)
cout<<Random(0, 50, true)<<" ";
cout<<endl;
cout<<"測試數據排序"<<endl;
vector<int> v12, v13;
RandomVecInt(v12, 10,0, 20);
CoutVecT(v12);
SortVec(v12, v13, true, true);
CoutVecT(v12);
CoutVecT(v13);
cout<<"等差數列:"<<endl;
vector<int> v14;
AriVecT(v14, 1, 2, 10);
CoutVecT(v14);
cout<<"等比數列:"<<endl;
vector<int> v15;
GeoVecT(v15, 1, 2, 10);
CoutVecT(v15);
cout<<"測試Fibonacci():"<<endl;
cout<<"Fibonacci(-1)="<<Fibonacci(-1)<<endl;
cout<<"Fibonacci(-1)="<<Fibonacci(-1)<<endl;
for(int fib=1; fib<11; fib++)
cout<<Fibonacci(fib)<<" ";
cout<<endl;
cout<<"測試FibVecInt:"<<endl;
vector<int> v16;
FibVecInt(v16,10);
CoutVecT(v16);
return 0;
}
//僅爲方便輸出容器的每一項
template<typename T>
void CoutVecT(const vector<T> &vec)
{
for(typename vector<T>::size_type si=0; si!=vec.size(); si++)
cout<<vec[si]<<" ";
cout<<endl;
}
//編譯命令:
// g++ MathFunc.cpp test1.cpp -o test1 && test1 -std=c++11(啓用C++11特性,在此不須要)
// g++ MathFunc.cpp test1.cpp -o test1 && test1
//=============
//運行結果:
//=============
// 5是質數
// 9不是質數
// 5不是徹底平方數
// 9是徹底平方數
// 27和18的最大公約數是:9
// 27和18的最小公倍數是:54
// 數組arr的最大公約數是:3
// 數組arr的最小公倍數是:72
// 容器v1的最大公約數是:3
// 容器v1的最小公倍數是:72
// -1的階乘是:0
// 0的階乘是:1
// 1的階乘是:1
// 2的階乘是:2
// 5的階乘是:120
// 13的階乘是:1932053504
// 15的階乘是:0
// 0-15的階乘爲:
// 1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800 479001600 1932053504
// -1234的逆序數是-4321
// -1的逆序數是-1
// 0的逆序數是0
// 1的逆序數是1
// 1234的逆序數是4321
// 123456的逆序數是654321
// 7
// 17之內有7個質數
// 2 3 5 7 11 13 17
// v3和:90
// v4和:0
// v5和:12
// v3後七項和:72
// v3平均:9
// v4平均:0
// v5平均:4
// v3方差:0
// v4方差:0
// v5方差:2.66667
// v3標準差:0
// v4標準差:0
// v5標準差:1.63299
// 數字分離
// 3
// 3
// 3
// 2 5 6
// 6 5 2
// 數字合成
// 56
// 166
// 65
// 175
// 數據反序
// 33 22 11
// 11 22 33
// 33 22 11
// 測試隨機數
// 11 7 47 7 31
// 測試數據排序
// 20 9 14 2 13 15 3 10 20 17
// 20 9 14 2 13 15 3 10 20 17
// 2 3 9 10 13 14 15 17 20
// 等差數列:
// 1 3 5 7 9 11 13 15 17 19
// 等比數列:
// 1 2 4 8 16 32 64 128 256 512
// 測試Fibonacci():
// Fibonacci(-1)=0
// Fibonacci(-1)=0
// 1 1 2 3 5 8 13 21 34 55
// 測試FibVecInt:
// 1 1 2 3 5 8 13 21 34 55
//=============
01
#TYSoft GNU GCC MinGW g++ Makefile
02
#加強的數學函數庫的測試
03
04
#=====設置編譯器選項=====
05
CXX
= g++
06
CCFLAGS
=
07
#-ansi -W -Wall
08
#=====設置文件變量=====
09
SOFTNMAE
= TYtest
10
OBJECTS
= MathFunc.o test1.o
11
LOCFLAGS
= ../Include/MathFunc.h
12
#======================
13
14
#=====將.o文件link成.exe文件=====
15
$(SOFTNMAE) :
$(OBJECTS)
16
$(CXX)
$(CCFLAGS)
$(OBJECTS) -o
$(SOFTNMAE)
17
18
#=====將.cpp文件編譯成.o文件=====
19 MathFunc.o :
$(LOCFLAGS)
20 test1.o :
$(LOCFLAGS)
21
22
#=====清理文件=====
23 .PHONY : clean
24 clean :
25 -rm
$(SOFTNMAE)
$(OBJECTS)