• 自己模拟实现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 << "	";
    347     drow_line(35);
    348 
    349     cout << "				*** 主菜单选项 ***" << endl;
    350 
    351     cout << "	";
    352     drow_line(35);
    353 
    354     cout << left;
    355     cout << "	        " << setw(25) << "1. 取整 Int( x )";
    356     cout << setw(25) << "2. 计算 sinh( x )" << endl;
    357     cout << "	        " << setw(25) << "3. 计算 sin( x )";
    358     cout << setw(25) << "4. 计算 n^2 " << endl;
    359     cout << "	        " << setw(25) << "5. 计算 n!";
    360     cout << setw(25) << "6. 计算 cosh( x ) " << endl;
    361     cout << "	        " << setw(25) << "7. 计算 cos( x )";
    362     cout << setw(25) << "8. 计算 x^y" << endl;
    363     cout << "	        " << setw(25) << "9. 计算 y√x ";
    364     cout << setw(25) << "10. 计算 tanh( x ) " << endl;
    365     cout << "	        " << setw(25) << "11. 计算 Π";
    366     cout << setw(25) << "12. 计算 tan( x )" << endl;
    367     cout << "	        " << setw(25) << "13. 计算 x^3";
    368     cout << setw(25) << "14. 计算 3√x" << endl;
    369     cout << "	        " << setw(25) << "0. 退出系统"  << endl;
    370 
    371     cout << "	";
    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 }

    执行结果:

  • 相关阅读:
    (二十九)动态单元格
    (二十八)QQ好友列表的展开收缩
    (二十七)QQ好友列表的实现
    (二十六)静态单元格(Cell)
    (二十五)键盘的设置与TextField细节处理
    poj 1734 Sightseeing trip
    BZOJ 2200: [Usaco2011 Jan]道路和航线
    LUOGU P1073 最优贸易
    poj 3662 Telephone Lines
    poj 3539 Elevator
  • 原文地址:https://www.cnblogs.com/CocoonFan/p/3164221.html
Copyright © 2020-2023  润新知