自己模拟实现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 }

执行结果:

 

posted @ 2013-07-01 04:46  Cocoon  阅读(1511)  评论(0编辑  收藏  举报