您的位置:首页 > 编程语言 > C语言/C++

增强的数学函数库(第1次发布,功能不断增加中)

2012-06-01 21:04 393 查看
/*- ==========================================================
*     文件名  :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,
4000
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
*
d86b
修改时间: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
//=============
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息