自己模拟实现math.h中的函数
之前一直都很迷惑pow()函数时怎么实现的,对于整数次的幂我还能很容易做到,但是对于分数次幂就不是那么好做了。需要一些高等数学级数的知识。
我这里实现了求ln(x), pow(double x, double y), exp(x), sin(x), cos(x), sinh(x), cosh(x), tanh(x), arctanh(x)等一些常见的函数功能。具体请看代码
1 /*============================================================================*\ 2 * 3 * 模拟实现 math.h 库中的函数 4 * 5 * 樊列龙 2013/7/1 6 * 7 \*============================================================================*/ 8 9 #include <iostream> 10 #include <iomanip> 11 #include <string> 12 #include <cstdlib> 13 #include <cstdio> 14 15 using namespace std; 16 17 typedef int MODE; // 计算sin(x)时采用弧度还是角度 18 const int BY_RADIDAN = 0; // 弧度 19 const int BY_ANGLE = 1; // 角度 20 21 const double RATIO = 0.01745329251994; // 角度转弧度的转换率 22 23 long Factorial( long x ); // 阶乘 24 double Pow( double x, double y = 2 ); // 求x^y 25 double Square( double x ); // 求平方 26 double Cube( double x ); // 求立方 27 double Sin( double x, MODE mode = BY_RADIDAN ); // 计算sin(x) 28 double Cos( double x , MODE mode = BY_RADIDAN ); // 计算cos(x) 29 double Tan( double x , MODE mode = BY_RADIDAN ); // 计算tan(x) 30 int Int(double x); // 取整, 不进行四舍五入 31 double Fabs( double x ); // 求绝对值 32 double Arctanh(double x); // 求achtanh() 33 double Ln(double x); // 求自然对数 34 double Exp( double x ); // 求e的x次幂 35 double Sinh( double x ); // 求双曲正弦 sinh() 36 double Cosh( double x ); // 求双曲余弦 cosh() 37 double Tanh(double x); // 求双曲正切 tanh() 38 double PI(); // 求圆周率 39 double gen(double x, double y); // 求根 40 41 42 // 计算阶乘 43 long Factorial( long x ) 44 { 45 if( 0 == x || 1 == x ) 46 { 47 return 1; 48 } 49 50 long ans = 1; 51 for( int i = 2; i <= x; i++ ) 52 { 53 ans *= i; 54 } 55 56 return ans; 57 } 58 59 60 // 计算求幂, 默认是平方 61 // x^y=e^(ln(x)*y) 62 double Pow(double x, double y) 63 { 64 return Exp( (Ln(x)*y) ); 65 } 66 67 // 求根 68 double gen(double x, double y) 69 { 70 return Pow(x,1/y); 71 } 72 73 // 计算绝对值 74 double Fabs( double x ) 75 { 76 if( x < -1e-9) 77 return -x; 78 return x; 79 } 80 81 int Int(double x) 82 { 83 return static_cast<int>(Fabs( x )); 84 } 85 86 // 利用泰勒级数算 sin(x) , 默认传入弧度 87 // sinx ≈x-(x^3)/3!+(x^5)/5!-(x^7)/7!-(x^9)/9!... 88 // 计算精度为7位 89 double Sin( double x, MODE mode ) 90 { 91 // 如果是角度则转换成弧度计算 92 if( BY_ANGLE == mode ) 93 { 94 x *= RATIO; 95 } 96 x = x - Int( (x/( 2 * PI() ) ) ) * 2 * PI(); 97 if( 0 == x ) 98 return 0; 99 100 double sum = 0, fs = x, fm = 1, t, t1 = 1; //求和、分子、分母、精度、t1表示符号位 101 int n=1; //项数 102 103 t = fs / fm; //精度赋值 104 while( Fabs(t) >= 1e-8) //循环条件 105 { 106 sum = sum + t; //求和 107 n++; //基数增加 108 fs = fs * x * x; //新分子 109 fm = fm * ( 2*n - 2) * ( 2*n - 1 ); //新分母 110 t1= -t1; //符号位 一正一负 111 t = t1 * ( fs / fm ); //精度 112 } 113 114 return sum; 115 } 116 117 // cos(x) = 1 - (x^2)/2! + (x^4)/4!...... 118 // 结果精度为7位 119 double Cos( double x , MODE mode) 120 { 121 double term,sum; 122 int n = 2; 123 124 sum = 1.0; 125 term = 1.0; 126 127 while(Fabs(term) > 1e-7) 128 { 129 term = term * x * x / (n * (n-1)) * (-1.0); 130 sum = sum + term; 131 n += 2; 132 } 133 134 return sum; 135 } 136 137 // tanθ = sinθ / cosθ 138 // 结果精度为7位 139 double Tan( double x , MODE mode) 140 { 141 return ( Sin(x) / Cos(x) ); 142 } 143 144 145 // 计算 x^2 146 double Square( double x ) 147 { 148 return ( x*x ); 149 } 150 151 // 计算 x^3 152 double Cube( double x ) 153 { 154 return ( x*x*x ); 155 } 156 157 158 // arctanh(x)= x + x^3/3 + x^5/5 + ... (x≤1) 159 // 求sinh(y) 会用到 160 // 精度为7位 161 double Arctanh(double x) 162 { 163 int n = 1; 164 double sum = 0, term = x, numer = x, denom = 1; 165 while(Fabs(term) > 1e-8) 166 { 167 sum += term; // 求和 168 numer = numer * x * x; // 分子 169 denom = n+2; // 分母 170 term = numer/denom; // 精度 171 n += 2; // 计数 172 } 173 174 return sum; 175 } 176 177 178 // ln(x) = 2 arctanh((x-1)/(x+1)) 179 // 调用了Arctanh(double) 方法 180 double Ln(double x) 181 { 182 return 2 * Arctanh((x-1)/(x+1)); 183 } 184 185 // 求e^x 用于Pow( double, double )调用 186 // e^x = 1+x+(x^2)/2!+(x^3)/3!+... 187 // 精度为7位 188 double Exp( double x ) 189 { 190 double ret = 1, term = x, numer = x, denom = 1;; 191 int n = 1; 192 while(Fabs(term) > 1e-8) 193 { 194 ret += term; // 求和 195 numer *= x; // 分子 196 denom = denom * (n+1); // 分母 197 n++; // 累加 198 term = numer/denom; // 精度 199 } 200 201 return ret; 202 203 } 204 205 // sinh(x)=(exp(x) - exp(-x)) / 2.0 206 // 精度为7位 207 double Sinh(double x) 208 { 209 return ( ( Exp(x) - Exp(-x) ) / 2.0 ); 210 } 211 212 // cosh(x)=(exp(x) + exp(-x)) / 2.0; 213 // 精度为7位 214 double Cosh(double x) 215 { 216 return ( ( Exp(x) + Exp(-x) ) / 2.0 ); 217 } 218 219 // tanh(x) = sinh(x) / cosh(x); 220 // 精度为7位 221 double Tanh(double x) 222 { 223 return ( Sinh(x) / Cosh(x) ); 224 } 225 226 227 // 求PI: pi/4 = 1 - 1/3 + 1/5 - 1/7... 228 double PI() 229 { 230 int a = 3, b = 1; 231 double m = 1.0, sum = 1.0; 232 233 while( Fabs(m) > 1e-7 ) 234 { 235 b = -b; 236 m = double(b) / a; 237 sum = sum + m; 238 a = a + 2; 239 } 240 return 4 * sum; 241 } 242 243 244 //============================================================================== 245 void drow_line(int i = 39,string s = "━", bool newline = false) 246 { 247 if(newline) cout << endl; 248 while(i--) 249 cout << s; 250 cout << endl; 251 } 252 253 void cls() 254 { 255 system("cls"); 256 } 257 258 void pause() 259 { 260 system("pause"); 261 //getchar(); 262 } 263 264 // 菜单选项 265 void menu_option(int& menu_op, 266 int max = 14, 267 int min = 0, 268 string s = " 请选择相应的菜单选项>>> ", 269 string error = " ERROR:请选择正确的菜单选项! >>> ") 270 { 271 cout << s; 272 cin >> menu_op; 273 while(cin.fail() || menu_op < min || menu_op > max) 274 { 275 cout << error; 276 cin.clear(); 277 fflush(stdin); 278 cin >> menu_op; 279 } 280 } 281 282 // 选择逻辑处理 283 bool choos() 284 { 285 string contin; 286 while(true) 287 { 288 getline(cin, contin); 289 if(contin == "Y" || contin == "y" || contin == "是") 290 { 291 return true; 292 } 293 else if(contin == "N" || contin == "n" || contin == "否") 294 { 295 return false; 296 } 297 else 298 { 299 cout << " 提示:请输入(Y/N)!>>> "; 300 } 301 } 302 303 } 304 305 bool check_input(int& x, 306 string str = " 请输入数据x:", 307 string err = " 输入数据格式有误!") 308 { 309 cout << str; 310 cin >> x; 311 if(cin.good()) 312 return true; 313 cout << err << endl; 314 return false; 315 } 316 317 bool check_input(double& x, 318 string str = " 请输入数据 x:", 319 string err = " 输入数据格式有误!") 320 { 321 cout << str; 322 cin >> x; 323 if(cin.good()) 324 return true; 325 cout << err << endl; 326 return false; 327 } 328 329 void print_result(double ans, string str ) 330 { 331 cout << str << " = " << ans << endl; 332 pause(); 333 } 334 335 //============================================================================== 336 337 /** 338 * 339 * 主菜单 340 */ 341 void menu_main() 342 { 343 cls(); 344 cout << endl << endl << endl; 345 346 cout << "\t"; 347 drow_line(35); 348 349 cout << "\t\t\t\t*** 主菜单选项 ***" << endl; 350 351 cout << "\t"; 352 drow_line(35); 353 354 cout << left; 355 cout << "\t " << setw(25) << "1. 取整 Int( x )"; 356 cout << setw(25) << "2. 计算 sinh( x )" << endl; 357 cout << "\t " << setw(25) << "3. 计算 sin( x )"; 358 cout << setw(25) << "4. 计算 n^2 " << endl; 359 cout << "\t " << setw(25) << "5. 计算 n!"; 360 cout << setw(25) << "6. 计算 cosh( x ) " << endl; 361 cout << "\t " << setw(25) << "7. 计算 cos( x )"; 362 cout << setw(25) << "8. 计算 x^y" << endl; 363 cout << "\t " << setw(25) << "9. 计算 y√x "; 364 cout << setw(25) << "10. 计算 tanh( x ) " << endl; 365 cout << "\t " << setw(25) << "11. 计算 Π"; 366 cout << setw(25) << "12. 计算 tan( x )" << endl; 367 cout << "\t " << setw(25) << "13. 计算 x^3"; 368 cout << setw(25) << "14. 计算 3√x" << endl; 369 cout << "\t " << setw(25) << "0. 退出系统" << endl; 370 371 cout << "\t"; 372 drow_line(35); 373 374 cout << endl << endl; 375 drow_line(39,"><"); 376 cout << endl; 377 378 } 379 380 int main() 381 { 382 int ansInt; 383 double ans; 384 int xi; 385 double x,y; 386 387 while(true) 388 { 389 cls(); 390 menu_main(); 391 int option; 392 menu_option(option); // 选择功能 393 switch(option) 394 { 395 case 0 : 396 cout << "是否退出?(Y/N)"; 397 if(choos()) 398 exit(0); 399 break; 400 case 1: 401 check_input(x); 402 ansInt = Int(x); 403 drow_line(39,"**"); 404 cout << "Int(" << x << ") = " << ansInt << endl; 405 pause(); 406 break; 407 case 2: 408 check_input(x); 409 ans = Sinh(x); 410 drow_line(39,"**"); 411 cout << "sinh(" << x << ") = " << ans << endl; 412 pause(); 413 break; 414 case 3: 415 check_input(x); 416 ans = Sin(x); 417 drow_line(39,"**"); 418 cout << "sin(" << x << ") = " << ans << endl; 419 pause(); 420 break; 421 case 4: 422 check_input(x); 423 ans = Square(x); 424 drow_line(39,"**"); 425 cout << x << "^2 = " << ans << endl; 426 pause(); 427 break; 428 case 5: 429 check_input(xi, " 请输入整数n: "); 430 ansInt = Factorial(xi); 431 drow_line(39,"**"); 432 cout << xi << "! = " << ansInt << endl; 433 pause(); 434 break; 435 case 6: 436 check_input(x); 437 ans = Cosh(x); 438 drow_line(39,"**"); 439 cout << "cosh(" << x << ") = " << ans << endl; 440 pause(); 441 break; 442 case 7: 443 check_input(x); 444 ans = Cos(x); 445 drow_line(39,"**"); 446 cout << "cos(" << x << ") = " << ans << endl; 447 pause(); 448 break; 449 case 8: 450 check_input(x, " 请输入数据 x y : "); 451 check_input(y, ""); 452 ans = Pow(x,y); 453 drow_line(39,"**"); 454 cout << x << "^" << y << " = " << ans << endl; 455 pause(); 456 break; 457 case 9: 458 check_input(x, " 请输入数据 x y : "); 459 check_input(y, ""); 460 ans = gen(x,y); 461 drow_line(39,"**"); 462 cout << y << "√" << x << " = " << ans << endl; 463 pause(); 464 break; 465 case 10: 466 check_input(x); 467 ans = Tanh(x); 468 drow_line(39,"**"); 469 cout << "tanh(" << x << ") = " << ans << endl; 470 pause(); 471 break; 472 case 11: 473 ans = PI(); 474 drow_line(39,"**"); 475 cout << "π = " << ans << endl; 476 pause(); 477 break; 478 case 12: 479 check_input(x); 480 ans = Tan(x); 481 drow_line(39,"**"); 482 cout << "tan(" << x << ") = " << ans << endl; 483 pause(); 484 break; 485 case 13: 486 check_input(x); 487 ans = Cube(x); 488 drow_line(39,"**"); 489 cout << x << "^3 = " << ans << endl; 490 pause(); 491 break; 492 case 14: 493 check_input(x); 494 ans = gen(x,3); 495 drow_line(39,"**"); 496 cout << "3√" << x << " = " << ans << endl; 497 pause(); 498 break; 499 default: 500 break; 501 } 502 } 503 return 0; 504 }
执行结果: