增强的数学函数库(第1次发布,功能不断增加中)
1 /*- ========================================================== 2 * 文件名 :MathFunc.h 3 * 开发人员:袁培荣 4 * 当前版本:1.3.3.2595 (第1次发布,功能不断增加中) 5 * 创建时间:2012-05-28 6 * 修改时间:2012-05-30 7 * 功能说明:增强的数学函数库的声明 8 * 版权说明:版权所有 袁培荣 YuanPeirong 9 * 编译环境:Windows 7(x64) SP1 简体中文专业版 10 * 编译器: Visual Studio 2010 SP1(中文旗舰版) 11 MinGW 20120426 GNU GCC 4.6.2 12 Visual C++ 6.0 SP6(中文企业版) 13 - ==========================================================*/ 14 15 //编译测试情况: 16 // 1.Visual Studio 2010 SP1(中文旗舰版): 17 // 在Release和Debug下都编译通过,测试运行正常。 18 // 2.MinGW 20120426 GNU GCC 4.6.2: 19 // 编译通过,测试运行正常。 20 // 3.Visual C++ 6.0 SP6(中文企业版) 21 // 未测试。 22 23 #ifndef MathFunc_H_TYCppStdLib //防止头文件重复包含 24 #define MathFunc_H_TYCppStdLib 25 26 #ifdef MathFunc_DLL_API //为导出DLL预留 27 #else 28 #define MathFunc_DLL_API _declspec(dllimport) 29 #endif 30 31 #include <cstdlib> 32 #include <cmath> 33 #include <ctime> 34 #include <vector> //vector容器 35 #include <algorithm> //泛型算法 36 #include <numeric> //泛化算法 37 //#include <functional> //标准库的函数对象类型在此定义 38 39 using namespace std; 40 41 namespace TYCppStdLib //所有功能都封装在命名空间TYCppStdLib中 42 { 43 //产生一个随机整数 44 int Random( 45 int minValue=-32768, //设置数据的最大值(包含) 46 int maxValue=32767, //设置数据的最大值(包含) 47 bool isPrime=false //是否必须要返回质数 48 ); 49 50 //产生随机纯小数 51 double Random( 52 double minValue=0, //设置数据的最小值(包含) 53 double maxValue=1, //设置数据的最大值(包含) 54 bool get0and1=false //指明是否可以产生0和1 55 ); 56 57 //产生一组随机整数(此函数是以前写的,将要被我弃用,因为使用了不安全的数组) 58 //建议使用功能更加强大的 RandomVecInt函数(在下文中定义) 59 bool Random( 60 int *data, //用于存放产生的整数的数组首地址 61 int num, //设置要产生的数据个数 62 int minValue=-32768, //设置数据的最小值(包含) 63 int maxValue=32767, //设置数据的最大值(包含) 64 bool different=false //设置数据是否要互不相同 65 ); 66 67 //为Random函数定义相应的类,方便生成函数对象作为泛型算法的发生器 68 class Random_cls 69 { 70 private: 71 int minValue; 72 int maxValue; 73 bool isPrime; 74 public: 75 Random_cls(int min, int max, bool isp); 76 int operator()(); 77 }; 78 79 bool IsPrime(int n); //判断质数 80 //获取n以内(含n)的所有质数的个数 81 int GetPrime(int n); 82 //获取n以内(含n)的所有质数,并返回质数的个数 83 int GetPrime(int n, vector<int> &vec); 84 //int GetPrime(int n, int *p); //数组版本,因不安全,不想支持 85 bool IsSquare(int n); //判断完全平方数 86 87 //求两个数的最大公约数 88 int GetGCD(int m, int n); 89 //求一组数据的最大公约数(不安全,不推荐使用) 90 int GetGCD(const int *p, int count); 91 //或者是int GetGCD(const int p[], int count); 92 //求一组数据的最大公约数(安全,推荐使用) 93 int GetGCD(vector<int> &vec); 94 95 //求两个数的最小公倍数 96 int GetLCM(int m, int n); 97 //求一组数据的最小公倍数(不安全,不推荐使用) 98 int GetLCM(const int *p, int count); 99 //或者是int GetLCM(const int p[], int count); 100 //求一组数据的最小公倍数(安全,推荐使用) 101 int GetLCM(vector<int> &vec); 102 103 int GetFactorial(int n); //求阶乘(13以内)(非递归和递归方式实现) 104 //获得0到n的阶乘结果(n超过13时设为13) 105 //这里不用到GetFactorial,因为效率太低 106 void FacVecInt(vector<int> &vec, int n); 107 108 int InversionData(int n); //求整数的逆序数,如6589返回9856 109 110 //以下用到 vector 的函数都可以写相应的数组版本 111 //但是因为数组是不安全的东西,不想再支持数组 112 113 //获取数字的位数 114 int DivideDigit(int n); 115 //获取数字的各个位上的数值,并返回分离出的数字个数 116 int DivideDigit( 117 int n, //待求数字 118 vector<int> &vec, //存储结果 119 bool forward=true //ture:高位在前存储,false:低位在前存储 120 ); 121 //获取数字的各个位上的数值(高位在前),并返回分离出的数字个数 122 //int DivideDigitA(int n, vector<int> &vec); //不再需要 123 //获取数字的各个位上的数值(低位在前),并返回分离出的数字个数 124 //int DivideDigitB(int n, vector<int> &vec); //不再需要 125 126 //将一组数据按位合成一个数 127 int JoinDigit( 128 const vector<int> &vec, //一组数据 129 bool forward=true, //ture:高位在前,false:低位在前 130 bool onlyBit=false //数据中的每一位是否只取其个位 131 ); 132 133 //生成一组随机数据(用随机数据初始化vector<int>) 134 void RandomVecInt( 135 vector<int> &vec, //存放数据的容器 136 int num, //产生数据的个数 137 int minValue=-32768, //设置数据的最大值(包含) 138 int maxValue=32767, //设置数据的最大值(包含) 139 bool isPrime=false //产生的数据是否必须为质数 140 ); 141 142 //求Fibonacci数列的第N项 F1=1 F2=1 F3=2 ……(非递归和递归方式实现) 143 int Fibonacci(int n); 144 //求Fibonacci数列的前N项(用Fibonacci数列初始化vector<int>) 145 //这里不用到Fibonacci函数,因为效率太低 146 void FibVecInt(vector<int> &vec, int num); 147 148 //求一组数据的和 149 template<typename T> 150 T GetSum(const vector<T> &vec); 151 // template<typename T> //初始实现版本 152 // T GetSum(typename vector<T>::const_iterator start, typename vector<T>::const_iterator end); 153 //调用方式:T sum=GetSum(s, e)或者 GetSum<T>(s, e) 154 template<typename T, typename InputIterator> //更加泛化的实现版本 155 T GetSum(InputIterator start, InputIterator end); 156 //调用方式:T sum=GetSum(s, e)或者 GetSum<T>(s, e) 157 158 //求一组数据的算术平均数(涉及到除法,因此返回值转为double,下同) 159 template<typename T> 160 double GetMean(const vector<T> &vec); 161 162 //求一组数据的方差 163 template<typename T> 164 double GetVariance(const vector<T> &vec); 165 166 //求一组数据的标准差 167 template<typename T> 168 double GetStDev(const vector<T> &vec); 169 170 //将一组数据反序,并覆盖原数据 171 template<typename T> 172 void InverseVec(vector<T> &vec); //结果覆盖原数据 173 //将一组数据反序,不覆盖原数据 174 template<typename T> 175 void InverseVec( 176 const vector<T> &vec1, //原数据 177 vector<T> &vec2 //逆序数据 178 ); 179 180 //比较两个数的大小 181 template<typename T> 182 bool IsBig(const T &m, const T &n); 183 template<typename T> 184 bool IsSmall(const T &m, const T &n); 185 186 //将一组数据进行排序,并覆盖原数据 187 template<typename T> 188 void SortVec( 189 vector<T> &vec, //结果覆盖原数据 190 bool smallToBig=true, //ture:从小到大,false:从大到小 191 bool eraseUnique=false //ture:去除重复值,false:不去除重复值 192 ); 193 //将一组数据进行排序,不覆盖原数据 194 template<typename T> 195 void SortVec( 196 const vector<T> &vec1, //原数据 197 vector<T> &vec2, //逆序数据 198 bool smallToBig=true, //ture:从小到大,false:从大到小 199 bool eraseUnique=false //ture:去除重复值,false:不去除重复值 200 ); 201 202 //生成等差数列(Arithmetic Sequence)(用等差数列初始化vector<T>) 203 template<typename T> 204 void AriVecT( 205 vector<T> &vec, //存储数据 206 T fisrt, //首项 207 T tolerance, //公差 208 T num //项数 209 ); 210 211 //生成等比数列(Geometric Sequence)(用等比数列初始化vector<T>) 212 template<typename T> 213 void GeoVecT( 214 vector<T> &vec, //存储数据 215 T fisrt, //首项 216 T comRatio, //公比 217 T num //项数 218 ); 219 220 // 仅为测试 221 // template<typename T> 222 // T GetTest(T n); 223 224 } 225 226 //为了兼容各编译器,特别是VC++6.0这种低级的旧版本编译器 227 //只好采用模板的包含编译模式 228 //模板的实现放在.hpp文件中,编译时不单独编译 229 //而事实上, Visual Studio 2010也不能采用更先进的分离编译模式 230 //而对C++标准支持得最好的MinGW也不能支持更先进的分离编译模式 231 //除了国外极少数的冷门商业编译器支持分离编译模式 232 //我现有的编译器都不只支持,因此只能头文件反向包含源文件的做法 233 //采用了boost的做法,将其反缀名定为 .hpp ,即 .h + .cpp 234 #include "MathFunc.hpp" 235 //在编译时,应将此hpp文件当做头文件而非源文件,即不单独编译 236 #endif 237 238 //摘自:SGI STL 239 /* template<typename _InputIterator, typename _Tp> 240 inline _Tp 241 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) 242 { 243 // concept requirements 244 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) 245 __glibcxx_requires_valid_range(__first, __last); 246 247 for (; __first != __last; ++__first) 248 __init = __init + *__first; 249 return __init; 250 } */
1 /*- ========================================================== 2 * 文件名 :MathFunc.cpp 3 * 开发人员:袁培荣 4 * 当前版本:1.3.3.2595 (第1次发布,功能不断增加中) 5 * 创建时间:2012-05-28 6 * 修改时间:2012-05-30 7 * 功能说明:增强的数学函数库的实现 8 * 版权说明:版权所有 袁培荣 YuanPeirong 9 * 编译环境:Windows 7(x64) SP1 简体中文专业版 10 * 编译器: Visual Studio 2010 SP1(中文旗舰版) 11 MinGW 20120426 GNU GCC 4.6.2 12 Visual C++ 6.0 SP6(中文企业版) 13 - ==========================================================*/ 14 15 //编译测试情况: 16 // 1.Visual Studio 2010 SP1(中文旗舰版): 17 // 在Release和Debug下都编译通过,测试运行正常。 18 // 2.MinGW 20120426 GNU GCC 4.6.2: 19 // 编译通过,测试运行正常。 20 // 3.Visual C++ 6.0 SP6(中文企业版) 21 // 未测试。 22 23 #ifndef MathFunc_DLL_ForAPI 24 #define MathFunc_DLL_ForAPI 25 26 #define MathFunc_DLL_API _declspec(dllexport) //为导出DLL预留 27 28 #endif 29 30 #include "../Include/MathFunc.h" 31 32 using namespace std; 33 using namespace TYCppStdLib; 34 35 //产生一个随机整数 36 int TYCppStdLib::Random( 37 int minValue, //设置数据的最大值(包含) 38 int maxValue, //设置数据的最大值(包含) 39 bool isPrime //是否必须要返回质数 40 ) 41 { 42 if(maxValue<minValue) 43 return 0;//return false; 44 if(minValue<-32768) 45 minValue=-32768; 46 if(maxValue>32767) 47 maxValue=32767; 48 int ix; 49 static bool randomFisrt=true; 50 if(randomFisrt) 51 srand(time(static_cast<time_t>(0))); 52 randomFisrt=false; 53 ix=rand(); 54 ix=ix%(maxValue-minValue+1)+minValue; 55 if(!isPrime) 56 return ix; 57 bool isp=IsPrime(ix); 58 if(isp) 59 return ix; 60 while(!isp) 61 { 62 ix=rand(); 63 ix=ix%(maxValue-minValue+1)+minValue; 64 isp=IsPrime(ix); 65 } 66 return ix; 67 } 68 69 //产生随机纯小数 70 double TYCppStdLib::Random(double minValue, double maxValue, bool get0and1) 71 { 72 if(maxValue<minValue) 73 return 0;//return false; 74 if(minValue<0) 75 minValue=0; 76 if(maxValue>1) 77 maxValue=1; 78 double dx; 79 int ix1, ix2; 80 ix1=(int)(minValue*32767); 81 ix2=(int)(maxValue*32767); 82 ix1=Random(ix1, ix2); 83 if(false==get0and1 && 0==minValue && 1==maxValue) 84 { 85 if(!ix1) 86 ix1=1; 87 if(ix1==32767) 88 ix1=32766; 89 } 90 dx=(double)(ix1)/32767; 91 return dx; 92 } 93 94 //产生一组随机整数(此函数是以前写的,将要被我弃用,因为使用了不安全的数组) 95 bool TYCppStdLib::Random(int *data, int num, int minValue, int maxValue, bool different) 96 { 97 98 if(num<1 || maxValue<minValue) 99 return false; 100 if(minValue<-32768) 101 minValue=-32768; 102 if(maxValue>32767) 103 maxValue=32767; 104 if(different && (maxValue-minValue+1)<num) 105 return false; 106 int ii, ij, ix; 107 for(ii=0;ii<num;ii++) 108 { 109 while(1) 110 { 111 ix=Random(minValue, maxValue); 112 if(!different) 113 break; 114 for(ij=0;ij<ii;ij++) 115 { 116 if(ix==*(data+ij)) 117 break; 118 } 119 if(ij==ii) 120 break; 121 } 122 *(data+ii)=ix; 123 } 124 return true; 125 } 126 127 //以下的函数是正确的,只是将数组形参写成指针形式更好,因此弃用 128 // 产生一批随机整数 129 // bool Random( 130 // int data[], //用于存放产生的整数的数组 131 // int num, //设置要产生的数据个数 132 // int minValue=-32768, //设置数据的最小值(包含) 133 // int maxValue=32767,//设置数据的最大值(包含) 134 // bool different=false //设置数据是否要互不相同 135 // ); 136 137 // bool Random(int data[], int num, int minValue, int maxValue, bool different) 138 // { 139 140 // if(num<1 || maxValue<minValue) 141 // return false; 142 // if(minValue<-32768) 143 // minValue=-32768; 144 // if(maxValue>32767) 145 // maxValue=32767; 146 // if(different && (maxValue-minValue+1)<num) 147 // return false; 148 // int ii, ij=0, ix; 149 // for(ii=0;ii<num;ii++) 150 // { 151 // while(1) 152 // { 153 // ix=Random(minValue, maxValue); 154 // if(!different) 155 // break; 156 // for(ij=0;ij<ii;ij++) 157 // { 158 // if(ix==data[ij]) 159 // break; 160 // } 161 // if(ij==ii) 162 // break; 163 // } 164 // data[ii]=ix; 165 // } 166 // return true; 167 // } 168 169 //为Random函数定义相应的类,方便生成函数对象作为泛型算法的发生器 170 TYCppStdLib::Random_cls::Random_cls(int min, int max, bool isp) 171 { 172 minValue=min; 173 maxValue=max; 174 isPrime=isp; 175 } 176 177 int TYCppStdLib::Random_cls::operator()() 178 { 179 return Random(minValue, maxValue, isPrime); 180 } 181 182 //判断质数 183 bool TYCppStdLib::IsPrime(int n) 184 { 185 n=abs(n); //允许n是负数 186 if(n<2) 187 return false; 188 int m=static_cast<int>(sqrt(static_cast<double>(n)))+1; 189 for(int i=2; i<m+1; i++) //i<m或i<m+1 190 if(n%i==0) 191 return false; 192 return true; 193 } 194 195 //获取n以内(含n)的所有质数的个数 196 int TYCppStdLib::GetPrime(int n) 197 { 198 if(n<2) 199 return 0; 200 if(2==n) 201 return 1; 202 int num=1; 203 for(int i=3; i<=n; i=i+2) 204 if(IsPrime(i)) 205 num++; 206 return num; 207 } 208 209 //获取n以内(含n)的所有质数,并返回质数的个数 210 int TYCppStdLib::GetPrime(int n, vector<int> &vec) 211 { 212 vec.clear(); 213 if(n<2) 214 return 0; 215 if(2==n) 216 { 217 vec.push_back(2); 218 return 1; 219 } 220 vec.push_back(2); 221 for(int i=3; i<=n; i=i+2) 222 if(IsPrime(i)) 223 vec.push_back(i); 224 return static_cast<int>(vec.size()); 225 } 226 227 //判断完全平方数 228 bool TYCppStdLib::IsSquare(int n) 229 { 230 if(n<0) 231 return false; 232 int m=static_cast<int>(sqrt(static_cast<double>(n))); 233 if(m*m==n) 234 return true; 235 return false; 236 } 237 238 //求两个数的最大公约数 239 int TYCppStdLib::GetGCD(int m, int n) 240 { 241 if(!m && !n) 242 return 0; 243 if(!m) 244 return n; 245 if(!n) 246 return m; 247 int r; 248 while(r=m%n) 249 { 250 m=n; 251 n=r; 252 } 253 return abs(n); 254 } 255 256 //求一组数据的最大公约数(不安全,不推荐使用) 257 int TYCppStdLib::GetGCD(const int *p, int count) 258 { 259 if(!p || count<2) 260 return 0; 261 int gcd=p[0]; 262 for(int i=1; i!=count; i++) 263 gcd=GetGCD(gcd,p[i]); 264 return abs(gcd); 265 } 266 267 //求一组数据的最大公约数(安全,推荐使用) 268 int TYCppStdLib::GetGCD(vector<int> &vec) 269 { 270 int vsize=vec.size(); 271 if(vsize<2) 272 return 0; 273 int gcd=vec[0]; 274 for(int i=1; i!=vsize; i++) 275 gcd=GetGCD(gcd, vec[i]); 276 return abs(gcd); 277 } 278 279 //求两个数的最小公倍数 280 int TYCppStdLib::GetLCM(int m, int n) 281 { 282 if(!m || !n) 283 return 0; 284 int lcm=m*n/GetGCD(m, n); //GetGCD(m, n)不会再返回0 285 return abs(lcm); //因为返回0的情况在前面已经排除 286 } 287 288 //求一组数据的最小公倍数(不安全,不推荐使用) 289 int TYCppStdLib::GetLCM(const int *p, int count) 290 { 291 if(!p || count<2) 292 return 0; 293 int lcm=p[0]; 294 for(int i=1; i!=count; i++) 295 lcm=GetLCM(lcm, p[i]); 296 return abs(lcm); 297 } 298 299 //求一组数据的最小公倍数(安全,推荐使用) 300 int TYCppStdLib::GetLCM(vector<int> &vec) 301 { 302 int vsize=vec.size(); 303 if(vsize<2) 304 return 0; 305 int lcm=vec[0]; 306 for(int i=1; i!=vsize; i++) 307 lcm=GetLCM(lcm, vec[i]); 308 return abs(lcm); 309 } 310 311 //求阶乘(13以内)(非递归) 312 int TYCppStdLib::GetFactorial(int n) 313 { 314 if(n<0 || n>13) 315 return 0; 316 if(n<2) 317 return 1; 318 int fac=1; 319 for(int i=2; i<=n; i++) 320 fac=fac*i; 321 return fac; 322 } 323 324 //以下为求阶乘的递归实现,两种方法效率几乎相同 325 //但为减小函数重复调用开销,选择非递归方式 326 327 //求阶乘(13以内)(递归) 328 // int TYCppStdLib::GetFactorial(int n) 329 // { 330 // if(n<0 || n>13) 331 // return 0; 332 // if(n<2) 333 // return 1; 334 // return GetFactorial(n-1)*n; 335 // } 336 337 //获得0到n的阶乘结果(n超过13时设为13) 338 //这里不用到GetFactorial,因为效率太低 339 void TYCppStdLib::FacVecInt(vector<int> &vec, int n) 340 { 341 vec.clear(); 342 if(n<0) 343 return; 344 vec.push_back(1); 345 if(0==n) 346 return; 347 vec.push_back(1); 348 if(1==n) 349 return; 350 if(n>13) 351 n=13; 352 int fac=1; 353 for(int i=1; i!=n; i++) 354 { 355 fac=fac*(i+1); 356 vec.push_back(fac); 357 } 358 } 359 360 //求整数的逆序数,如6589返回9856 361 int TYCppStdLib::InversionData(int n) 362 { 363 int s=0; 364 while(n) 365 { 366 s=10*s+n%10; 367 n=n/10; 368 } 369 return s; 370 } 371 372 //获取数字的位数 373 int TYCppStdLib::DivideDigit(int n) 374 { 375 n=abs(n); 376 if(0==n) 377 return 1; 378 int num=0; 379 while(n) 380 { 381 n=n/10; 382 num++; 383 } 384 return num; 385 } 386 387 //获取数字的各个位上的数值,并返回分离出的数字个数 388 int TYCppStdLib::DivideDigit( 389 int n, //待求数字 390 vector<int> &vec, //存储结果 391 bool forward //ture:高位在前存储,false:低位在前存储 392 ) 393 { 394 n=abs(n); 395 vec.clear(); 396 int num=0; 397 if(0==n) 398 { 399 vec.push_back(0); 400 return 1; 401 } 402 if(forward) 403 { 404 while(n) 405 { 406 vec.insert(vec.begin(), n%10); 407 n=n/10; 408 num++; 409 } 410 } 411 else 412 { 413 while(n) 414 { 415 vec.push_back(n%10); 416 n=n/10; 417 num++; 418 } 419 } 420 return num; 421 } 422 423 //以下两个函数的功能已经被集成到上面的函数中 424 425 //获取数字的各个位上的数值(高位在前),并返回分离出的数字个数 426 // int TYCppStdLib::DivideDigitA(int n, vector<int> &vec) 427 // { 428 // n=abs(n); 429 // vec.clear(); 430 // if(0==n) 431 // { 432 // vec.push_back(0); 433 // return 1; 434 // } 435 // int num=0; 436 // while(n) 437 // { 438 // vec.insert(vec.begin(), n%10); 439 // n=n/10; 440 // num++; 441 // } 442 // return num; 443 // } 444 445 //获取数字的各个位上的数值(低位在前),并返回分离出的数字个数 446 // int TYCppStdLib::DivideDigitB(int n, vector<int> &vec) 447 // { 448 // n=abs(n); 449 // vec.clear(); 450 // if(0==n) 451 // { 452 // vec.push_back(0); 453 // return 1; 454 // } 455 // int num=0; 456 // while(n) 457 // { 458 // vec.push_back(n%10); 459 // n=n/10; 460 // num++; 461 // } 462 // return num; 463 // } 464 465 //将一组数据按位合成一个数 466 int TYCppStdLib::JoinDigit( 467 const vector<int> &vec, //一组数据 468 bool forward, //ture:高位在前,false:低位在前 469 bool onlyBit //数据中的每一位是否只取其个位 470 ) 471 { 472 if(vec.empty()) 473 return 0; 474 int sum=0; 475 vector<int>::size_type si; 476 if(forward) 477 { 478 for(si=0; si!=vec.size(); si++) 479 { 480 if(onlyBit) 481 sum=sum*10+(vec[si]%10); 482 else 483 sum=sum*10+vec[si]; 484 } 485 } 486 else 487 { 488 for(si=vec.size()-1; si!=-1; si--) 489 { 490 if(onlyBit) 491 sum=sum*10+(vec[si]%10); 492 else 493 sum=sum*10+vec[si]; 494 } 495 } 496 return sum; 497 } 498 499 //生成一组随机数据(用随机数据初始化vector<int>) 500 void TYCppStdLib::RandomVecInt( 501 vector<int> &vec, //存放数据的容器 502 int num, //产生数据的个数 503 int minValue, //设置数据的最大值(包含) 504 int maxValue, //设置数据的最大值(包含) 505 bool isPrime //产生的数据是否必须为质数 506 ) 507 { 508 vec.clear(); 509 if (num<1) 510 return; 511 vec.resize(num); 512 generate(vec.begin(), vec.end(), 513 Random_cls(minValue, maxValue, isPrime)); 514 return; 515 } 516 517 //求Fibonacci数列的第N项 F1=1 F2=1 F3=2 ……(非递归) 518 int TYCppStdLib::Fibonacci(int n) 519 { 520 if(n<1) 521 return 0; 522 if(1==n || 2==n) 523 return 1; 524 int fib; 525 int n_1=1; 526 int n_2=1; 527 for(int i=2; i!=n; i++) 528 { 529 fib=n_1+n_2; 530 n_2=n_1; 531 n_1=fib; 532 } 533 return fib; 534 } 535 536 //以下为求Fibonacci数列的第N项的递归实现,两种方法效率几乎相同 537 //但为减小函数重复调用开销,选择非递归方式 538 539 //求Fibonacci数列的第N项 F1=1 F2=1 F3=2 ……(递归) 540 // int TYCppStdLib::Fibonacci(int n) 541 // { 542 // if(n<1) 543 // return 0; 544 // if(1==n || 2==n) 545 // return 1; 546 // return (Fibonacci(n-1)+Fibonacci(n-2)); 547 // } 548 549 //求Fibonacci数列的前N项(用Fibonacci数列初始化vector<int>) 550 //这里不用到Fibonacci函数,因为效率太低 551 void TYCppStdLib::FibVecInt(vector<int> &vec, int num) 552 { 553 vec.clear(); 554 if(num<1) 555 return; 556 vec.push_back(1); 557 if(1==num) 558 return; 559 vec.push_back(1); 560 if(2==num) 561 return; 562 int n; 563 int n_1=1; 564 int n_2=1; 565 for(int i=2; i!=num; i++) 566 { 567 n=n_1+n_2; 568 vec.push_back(n); 569 n_2=n_1; 570 n_1=n; 571 } 572 } 573 574 // 仅为测试 575 // template<typename T> 576 // T TYCppStdLib::GetTest(T n) 577 // { 578 // return (-n); 579 // }
1 /*- ========================================================== 2 * 文件名 :MathFunc.hpp 3 * 开发人员:袁培荣 4 * 当前版本:1.3.3.2595 (第1次发布,功能不断增加中) 5 * 创建时间:2012-05-28 6 * 修改时间:2012-05-30 7 * 功能说明:增强的数学函数库的模板实现 8 * 版权说明:版权所有 袁培荣 YuanPeirong 9 * 编译环境:Windows 7(x64) SP1 简体中文专业版 10 * 编译器: Visual Studio 2010 SP1(中文旗舰版) 11 MinGW 20120426 GNU GCC 4.6.2 12 Visual C++ 6.0 SP6(中文企业版) 13 - ==========================================================*/ 14 15 //编译测试情况: 16 // 1.Visual Studio 2010 SP1(中文旗舰版): 17 // 在Release和Debug下都编译通过,测试运行正常。 18 // 2.MinGW 20120426 GNU GCC 4.6.2: 19 // 编译通过,测试运行正常。 20 // 3.Visual C++ 6.0 SP6(中文企业版) 21 // 未测试。 22 23 #ifndef MathFunc_HPP_TYCppStdLib //防止头文件重复包含 24 #define MathFunc_HPP_TYCppStdLib 25 26 #include <iostream> 27 //求一组数据的和 28 //export template<typename T> 29 template<typename T> 30 T TYCppStdLib::GetSum(const vector<T> &vec) 31 { 32 T sum=accumulate(vec.begin(), vec.end(), static_cast<T>(0)); 33 return sum; 34 } 35 36 //初始实现版本 37 // template<typename T> 38 // T TYCppStdLib::GetSum( 39 // typename vector<T>::const_iterator start 40 // , typename vector<T>::const_iterator end 41 // ) 42 // { 43 // T sum=accumulate(start, end, static_cast<T>(0)); 44 // return sum; 45 // } 46 47 //更加泛化的实现版本 48 template<typename T, typename InputIterator> 49 T TYCppStdLib::GetSum(InputIterator start, InputIterator end) 50 { 51 T sum=accumulate(start, end, static_cast<T>(0)); 52 return sum; 53 } 54 55 //求一组数据的算术平均数(涉及到除法,因此返回值转为double,下同) 56 template<typename T> 57 double TYCppStdLib::GetMean(const vector<T> &vec) 58 { 59 int num=static_cast<int>(vec.size()); 60 if(0==num) 61 return static_cast<double>(0); 62 T sum=accumulate(vec.begin(), vec.end(), static_cast<T>(0)); 63 return (static_cast<double>(sum))/(static_cast<double>(num)); 64 } 65 66 //求一组数据的方差(第1正确实现版本) 67 // template<typename T> 68 // double TYCppStdLib::GetVariance(const vector<T> &vec) 69 // { 70 // double mean=GetMean(vec); 71 // vector<double> temp; 72 // for(vector<double>::size_type si=0; si!=vec.size(); si++) 73 // { // vec为空也不会出错 74 // double vsi=static_cast<double>(vec[si]); 75 // temp.push_back((vsi-mean)*(vsi-mean)); 76 // } 77 // return GetMean(temp); 78 // } 79 80 //求一组数据的方差(优化实现版本) 81 //=== 82 //优化原因: 83 // 1.避免构造临时vector, 84 // 2.避免调用外部函数对临时vector的遍历 85 // 3.减少外部函数的调用次数 86 // 4.更快的处理空数据 87 // 5.减少内存占用 88 //=== 89 template<typename T> 90 double TYCppStdLib::GetVariance(const vector<T> &vec) 91 { 92 int num=static_cast<int>(vec.size()); 93 if(0==num) 94 return static_cast<double>(0); 95 double mean=GetMean(vec); 96 double sum=0; //sum和平均数有关,而平均数已经是double了 97 for(vector<double>::size_type si=0; si!=vec.size(); si++) 98 { 99 double vsi=static_cast<double>(vec[si]); 100 sum=sum+((vsi-mean)*(vsi-mean)); 101 } 102 return sum/(static_cast<double>(num)); 103 } 104 105 106 //求一组数据的标准差 107 template<typename T> 108 double TYCppStdLib::GetStDev(const vector<T> &vec) 109 { 110 return sqrt(GetVariance(vec)); 111 } 112 113 //将一组数据反序,并覆盖原数据 114 template<typename T> 115 void TYCppStdLib::InverseVec(vector<T> &vec) //结果覆盖原数据 116 { 117 vector<T> vec2; 118 for(typename vector<T>::size_type si=0; si!=vec.size(); si++) 119 vec2.insert(vec2.begin(), vec[si]); 120 vec=vec2; 121 return; 122 } 123 124 //将一组数据反序,不覆盖原数据 125 template<typename T> 126 void TYCppStdLib::InverseVec( 127 const vector<T> &vec1, //原数据 128 vector<T> &vec2 //逆序数据 129 ) 130 { 131 vec2.clear(); 132 for(typename vector<T>::size_type si=0; si!=vec1.size(); si++) 133 vec2.insert(vec2.begin(), vec1[si]); 134 return; 135 } 136 137 //比较两个数的大小 138 template<typename T> 139 bool TYCppStdLib::IsBig(const T &m, const T &n) 140 { 141 return m>=n; 142 } 143 template<typename T> 144 bool TYCppStdLib::IsSmall(const T &m, const T &n) 145 { 146 return m<n; 147 } 148 149 //将一组数据进行排序,并覆盖原数据 150 template<typename T> 151 void TYCppStdLib::SortVec( 152 vector<T> &vec, //结果覆盖原数据 153 bool smallToBig, //ture:从小到大,false:从大到小 154 bool eraseUnique //ture:去除重复值,false:不去除重复值 155 ) 156 { 157 if(smallToBig) 158 sort(vec.begin(), vec.end(), IsSmall<T>); //标准库有less和less_equal 159 //也可以写成sort(vec.begin(), vec.end()); 160 //但在MinGW和VS2010的Release下编译通过,运行正常 161 //VS2010的Debug下编译通过,运行错误 162 //但写成sort(vec.begin(), vec.end(), IsSmall<T>); 163 //在MinGW和VS2010的Release,Debug下都编译通过而运行正常 164 else 165 sort(vec.begin(), vec.end(), IsBig<T>); //标准库有greater和greater_equal 166 if(eraseUnique) 167 { 168 typename vector<T>::iterator end_unique= 169 unique(vec.begin(), vec.end()); 170 vec.erase(end_unique, vec.end()); 171 } 172 } 173 //将一组数据进行排序,不覆盖原数据 174 template<typename T> 175 void TYCppStdLib::SortVec( 176 const vector<T> &vec1, //原数据 177 vector<T> &vec2, //逆序数据 178 bool smallToBig, //ture:从小到大,false:从大到小 179 bool eraseUnique //ture:去除重复值,false:不去除重复值 180 ) 181 { 182 vec2=vec1; 183 SortVec(vec2, smallToBig, eraseUnique); 184 } 185 186 //生成等差数列(Arithmetic Sequence)(用等差数列初始化vector<T>) 187 template<typename T> 188 void TYCppStdLib::AriVecT( 189 vector<T> &vec, //存储数据 190 T fisrt, //首项 191 T tolerance, //公差 192 T num //项数 193 ) 194 { 195 vec.clear(); 196 if(num<1) 197 return; 198 for(int i=0; i!=num; i++) 199 { 200 vec.push_back(fisrt); 201 fisrt=fisrt+tolerance; 202 } 203 } 204 205 //生成等比数列(Geometric Sequence)(用等比数列初始化vector<T>) 206 template<typename T> 207 void TYCppStdLib::GeoVecT( 208 vector<T> &vec, //存储数据 209 T fisrt, //首项 210 T comRatio, //公比 211 T num //项数 212 ) 213 { 214 vec.clear(); 215 if(num<1) 216 return; 217 for(int i=0; i!=num; i++) 218 { 219 vec.push_back(fisrt); 220 fisrt=fisrt*comRatio; 221 } 222 } 223 224 #endif
1 /*- ========================================================== 2 * 文件名 :test1.cpp 3 * 开发人员:袁培荣 4 * 当前版本:1.3.3.2595 (第1次发布,功能不断增加中) 5 * 创建时间:2012-05-28 6 * 修改时间:2012-05-30 7 * 功能说明:增强的数学函数库的测试代码 8 * 版权说明:版权所有 袁培荣 YuanPeirong 9 * 编译环境:Windows 7(x64) SP1 简体中文专业版 10 * 编译器: Visual Studio 2010 SP1(中文旗舰版) 11 MinGW 20120426 GNU GCC 4.6.2 12 Visual C++ 6.0 SP6(中文企业版) 13 - ==========================================================*/ 14 15 //编译测试情况: 16 // 1.Visual Studio 2010 SP1(中文旗舰版): 17 // 在Release和Debug下都编译通过,测试运行正常。 18 // 2.MinGW 20120426 GNU GCC 4.6.2: 19 // 编译通过,测试运行正常。 20 // 3.Visual C++ 6.0 SP6(中文企业版) 21 // 未测试。 22 23 #include <iostream> 24 #include "../Include/MathFunc.h" 25 //#include <vector> //MathFunc.h中已经包含此头文件 26 27 28 using namespace std; 29 using namespace TYCppStdLib; 30 31 template<typename T> //仅为方便输出容器的每一项 32 void CoutVecT(const vector<T> &vec); 33 34 int main(int argc, char* argv[]) 35 { 36 if(IsPrime(5)) 37 cout<<"5是质数"<<endl; 38 else 39 cout<<"5不是质数"<<endl; 40 41 if(IsPrime(9)) 42 cout<<"9是质数"<<endl; 43 else 44 cout<<"9不是质数"<<endl; 45 46 if(IsSquare(5)) 47 cout<<"5是完全平方数"<<endl; 48 else 49 cout<<"5不是完全平方数"<<endl; 50 51 if(IsSquare(9)) 52 cout<<"9是完全平方数"<<endl; 53 else 54 cout<<"9不是完全平方数"<<endl; 55 56 cout<<"27和18的最大公约数是:"<<GetGCD(27, 18)<<endl; 57 cout<<"27和18的最小公倍数是:"<<GetLCM(27, 18)<<endl; 58 59 int arr[5]={6,9,36,18,72}; 60 cout<<"数组arr的最大公约数是:"<<GetGCD(arr, 5)<<endl; 61 cout<<"数组arr的最小公倍数是:"<<GetLCM(arr, 5)<<endl; 62 63 vector<int> v1; 64 v1.push_back(6); 65 v1.push_back(9); 66 v1.push_back(36); 67 v1.push_back(18); 68 v1.push_back(72); 69 cout<<"容器v1的最大公约数是:"<<GetGCD(v1)<<endl; 70 cout<<"容器v1的最小公倍数是:"<<GetLCM(v1)<<endl; 71 72 cout<<"-1的阶乘是:"<<GetFactorial(-1)<<endl; 73 cout<<"0的阶乘是:"<<GetFactorial(0)<<endl; 74 cout<<"1的阶乘是:"<<GetFactorial(1)<<endl; 75 cout<<"2的阶乘是:"<<GetFactorial(2)<<endl; 76 cout<<"5的阶乘是:"<<GetFactorial(5)<<endl; 77 cout<<"13的阶乘是:"<<GetFactorial(13)<<endl; 78 cout<<"15的阶乘是:"<<GetFactorial(15)<<endl; 79 cout<<"0-15的阶乘为:"<<endl; 80 vector<int> fac(10); 81 FacVecInt(fac, 15); 82 CoutVecT(fac); 83 84 cout<<"-1234的逆序数是"<<InversionData(-1234)<<endl; 85 cout<<"-1的逆序数是"<<InversionData(-1)<<endl; 86 cout<<"0的逆序数是"<<InversionData(0)<<endl; 87 cout<<"1的逆序数是"<<InversionData(1)<<endl; 88 cout<<"1234的逆序数是"<<InversionData(1234)<<endl; 89 cout<<"123456的逆序数是"<<InversionData(123456)<<endl; 90 91 vector<int> v2(10); 92 int i=17; 93 cout<<GetPrime(i)<<endl; 94 cout<<i<<"以内有"<<GetPrime(i, v2)<<"个质数"<<endl; 95 CoutVecT(v2); 96 97 vector<int> v3(10,9); 98 vector<int> v4; 99 vector<int> v5; 100 101 v5.push_back(2); //2+4+6=12 平均4 102 v5.push_back(4); //方差 (4+0+4)/3 103 v5.push_back(6); 104 105 cout<<"v3和:"<<GetSum(v3)<<endl; 106 cout<<"v4和:"<<GetSum(v4)<<endl; 107 cout<<"v5和:"<<GetSum(v5)<<endl; 108 109 vector<int>::iterator is=v3.begin(); 110 vector<int>::iterator ie=v3.end(); 111 is++; 112 is++; 113 cout<<"v3后七项和:"<<GetSum<int>(is, ie)<<endl; 114 115 cout<<"v3平均:"<<GetMean(v3)<<endl; 116 cout<<"v4平均:"<<GetMean(v4)<<endl; 117 cout<<"v5平均:"<<GetMean(v5)<<endl; 118 119 cout<<"v3方差:"<<GetVariance(v3)<<endl; 120 cout<<"v4方差:"<<GetVariance(v4)<<endl; 121 cout<<"v5方差:"<<GetVariance(v5)<<endl; 122 123 cout<<"v3标准差:"<<GetStDev(v3)<<endl; 124 cout<<"v4标准差:"<<GetStDev(v4)<<endl; 125 cout<<"v5标准差:"<<GetStDev(v5)<<endl; 126 127 cout<<"数字分离"<<endl; 128 int i2=256; 129 vector<int> v6(10,1); 130 vector<int> v7(10,2); 131 cout<<DivideDigit(i2)<<endl; 132 cout<<DivideDigit(i2, v6)<<endl; 133 cout<<DivideDigit(i2, v7, false)<<endl; 134 CoutVecT(v6); 135 CoutVecT(v7); 136 137 cout<<"数字合成"<<endl; 138 vector<int> v8; 139 v8.push_back(15); 140 v8.push_back(16); 141 cout<<JoinDigit(v8,true, true)<<endl; 142 cout<<JoinDigit(v8,true, false)<<endl; 143 cout<<JoinDigit(v8,false, true)<<endl; 144 cout<<JoinDigit(v8,false, false)<<endl; 145 146 cout<<"数据反序"<<endl; 147 vector<int> v9; 148 v9.push_back(11); 149 v9.push_back(22); 150 v9.push_back(33); 151 InverseVec(v9); 152 CoutVecT(v9); 153 154 vector<int> v10; 155 v10.push_back(11); 156 v10.push_back(22); 157 v10.push_back(33); 158 vector<int> v11(20); 159 InverseVec(v10, v11); 160 CoutVecT(v10); 161 CoutVecT(v11); 162 163 164 cout<<"测试随机数"<<endl; 165 for(int ii=0; ii<5; ii++) 166 cout<<Random(0, 50, true)<<" "; 167 cout<<endl; 168 169 cout<<"测试数据排序"<<endl; 170 vector<int> v12, v13; 171 RandomVecInt(v12, 10,0, 20); 172 CoutVecT(v12); 173 SortVec(v12, v13, true, true); 174 CoutVecT(v12); 175 CoutVecT(v13); 176 177 cout<<"等差数列:"<<endl; 178 vector<int> v14; 179 AriVecT(v14, 1, 2, 10); 180 CoutVecT(v14); 181 182 cout<<"等比数列:"<<endl; 183 vector<int> v15; 184 GeoVecT(v15, 1, 2, 10); 185 CoutVecT(v15); 186 187 cout<<"测试Fibonacci():"<<endl; 188 cout<<"Fibonacci(-1)="<<Fibonacci(-1)<<endl; 189 cout<<"Fibonacci(-1)="<<Fibonacci(-1)<<endl; 190 for(int fib=1; fib<11; fib++) 191 cout<<Fibonacci(fib)<<" "; 192 cout<<endl; 193 194 cout<<"测试FibVecInt:"<<endl; 195 vector<int> v16; 196 FibVecInt(v16,10); 197 CoutVecT(v16); 198 199 return 0; 200 } 201 202 //仅为方便输出容器的每一项 203 template<typename T> 204 void CoutVecT(const vector<T> &vec) 205 { 206 for(typename vector<T>::size_type si=0; si!=vec.size(); si++) 207 cout<<vec[si]<<" "; 208 cout<<endl; 209 } 210 211 //编译命令: 212 // g++ MathFunc.cpp test1.cpp -o test1 && test1 -std=c++11(启用C++11特性,在此不需要) 213 // g++ MathFunc.cpp test1.cpp -o test1 && test1 214 215 //============= 216 //运行结果: 217 //============= 218 // 5是质数 219 // 9不是质数 220 // 5不是完全平方数 221 // 9是完全平方数 222 // 27和18的最大公约数是:9 223 // 27和18的最小公倍数是:54 224 // 数组arr的最大公约数是:3 225 // 数组arr的最小公倍数是:72 226 // 容器v1的最大公约数是:3 227 // 容器v1的最小公倍数是:72 228 // -1的阶乘是:0 229 // 0的阶乘是:1 230 // 1的阶乘是:1 231 // 2的阶乘是:2 232 // 5的阶乘是:120 233 // 13的阶乘是:1932053504 234 // 15的阶乘是:0 235 // 0-15的阶乘为: 236 // 1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800 479001600 1932053504 237 // -1234的逆序数是-4321 238 // -1的逆序数是-1 239 // 0的逆序数是0 240 // 1的逆序数是1 241 // 1234的逆序数是4321 242 // 123456的逆序数是654321 243 // 7 244 // 17以内有7个质数 245 // 2 3 5 7 11 13 17 246 // v3和:90 247 // v4和:0 248 // v5和:12 249 // v3后七项和:72 250 // v3平均:9 251 // v4平均:0 252 // v5平均:4 253 // v3方差:0 254 // v4方差:0 255 // v5方差:2.66667 256 // v3标准差:0 257 // v4标准差:0 258 // v5标准差:1.63299 259 // 数字分离 260 // 3 261 // 3 262 // 3 263 // 2 5 6 264 // 6 5 2 265 // 数字合成 266 // 56 267 // 166 268 // 65 269 // 175 270 // 数据反序 271 // 33 22 11 272 // 11 22 33 273 // 33 22 11 274 // 测试随机数 275 // 11 7 47 7 31 276 // 测试数据排序 277 // 20 9 14 2 13 15 3 10 20 17 278 // 20 9 14 2 13 15 3 10 20 17 279 // 2 3 9 10 13 14 15 17 20 280 // 等差数列: 281 // 1 3 5 7 9 11 13 15 17 19 282 // 等比数列: 283 // 1 2 4 8 16 32 64 128 256 512 284 // 测试Fibonacci(): 285 // Fibonacci(-1)=0 286 // Fibonacci(-1)=0 287 // 1 1 2 3 5 8 13 21 34 55 288 // 测试FibVecInt: 289 // 1 1 2 3 5 8 13 21 34 55 290 //=============
Makefile语言: 增强的数学函数库的测试
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)
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)

浙公网安备 33010602011771号