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

/*- ==========================================================
*     文件名  :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)
相关文章
相关标签/搜索