今天,一如既往的训练c语言题,按照顺序,做到了14届蓝桥杯第三题,是一个关于近似值的问题,有点儿难度,尽管一上来我就有了思路,但是不得不承认,我想的办法不是最麻烦的,但是也够麻烦的了。题如下:
如果x的x次幂结果为10,你能计算出x的近似值吗?
显然,这个值是介于2和3之间的一个数字。
请把x的值计算到小数后6位(四舍五入),并填写这个小数值。
注意:只填写一个小数,不要写任何多余的符号或说明。
第一想法,很直观,就是用递归,函数嵌套在一起,最终得到需要的值,但是思路是有了,但是做后却无法正确输出,当然思路没问题,于是仔细看看代码,还是自己的定义的范围的问题(因为为了追求代码的高利用率,每次定义数据类型我总是追求刚好够用,杜绝浪费,于是作为新手的我总是出现这些小问题),另外旱出现一个弱智的问题,就是计数变量使用重复了,于是改动后,运算结果基本正确,这是我注意到一个问题,要求是四舍五入保留六位小数,而不是直接取整,于是我卡壳了,怎么破怎么破怎么破?心中默念三句咒语,果然不出所料,还是没想到破解办法,于是,呵呵,度娘,帮帮我。百度后,只找到了四舍五入保留整数部分的方法,因为c语言没有办法直接判别究竟是四舍还是五入,如是需要借助“0.5”来帮忙,加上0.5后取整即可,于是举一反三的我轻松的改动了部分解决了保留六位的办法。经过几番调试后,结果总算是正常了,并且每个数据类型都定义到刚刚好,不得不说我是个拮据的人,不想浪费内存。为此,我专门又查了查float型和double型表示的有效数字范围,float型可以表示6到7个有效数字,而double型可以表示15到16位有效数字,另外math函数库的内容也需要多加熟悉,代码如是矣:
#include <stdio.h>
#include <math.h>
double JinSiZhi=0;
int main(int argc, const char * argv[])
{
    double Jin_Si_Zhi(int j);
    float JSZ=0;
    JSZ=(int)(Jin_Si_Zhi(1)*1000000+0.5);
    JSZ=JSZ/1000000;
    printf("%f\n",JSZ);
    return 0;
}
double Jin_Si_Zhi(int j)
{
    if (j<9)
    {
        for (int i=0; i<10; i++)
        {
            JinSiZhi=JinSiZhi+i/pow(10, j-1);
            if (pow(JinSiZhi, JinSiZhi)>10)
            {
                JinSiZhi=JinSiZhi-1/pow(10, j-1);
                Jin_Si_Zhi(j+1);
                break;
            }
            JinSiZhi=JinSiZhi-i/pow(10, j-1);
        }
    }
    return JinSiZhi;
}    
做过这道题后,我并不满足于成功编译了这么简单,想要找一个更为简单的方法去解决它,于是辗转反侧终于想到了“二分法”,但是有了方向,但是没有具体的实施办法,于是没办法,我又去温习了一遍曾经的“二分法”,毕竟忘了具体的方法是做不出题的,寂静斟酌后,总算有所收获,简单的说涉及到三个变量:近似值下限,近似值上限以及中间值,可是我怎么才能让他循环分割并适时停止呢?没办法,我只好又去找度娘了,度娘告诉我:“小孩子,你要学的还有很多……努力学吧!”然后给了我一个宏,让我利用这个宏去做限定,这个宏是“1e-8”,好吧,我又不懂了,这都是啥玩意?于是我厚脸皮的又去百度了这个宏,明白了,他是表示1/100000000,经过度娘的提示,我最终想通了办法并作了出来,当然输出时的四舍五入的办法和上面的办法是一致的,经过最后的斟酌,我认为根本没必要“1e-8”,因为我系要保留六位小数,所以先求到七位就够了,保留的过多会导致循环次数增加过多,得不偿失,于是我就将“1e-8”改为了“1e-7”,终于,一切都正常编译了,并且达到了我目前认为的满意程度(因为我目前学识尚浅,有些地方还不知道怎么改会简化),经过整理,代码如下:
#include<stdio.h>//stdio 就是指 “standard input & output"(标准输入输出)头文件
#include<math.h>//数学函数库
#define eps 1e-7//定义宏1e-7,即1/10000000
int main()//主函数
{
    double l=2,r=3,mid=0;//根据题提示,正确答案位于2与3之间,定义l=2(初始下限),r=3(初始上限),使用二分法需要定义中间值mid,初始赋值为0
    float JSZ=0;//因为JSZ有效数字是七位,并且在float型表示范围内,故定义为float
    while(l+eps<r)//判定l加上定义的宏是否小于r,eps作用是保证程序不是死循环
    {
        mid=(l+r)/2;//取中间值
        if(pow(mid,mid)<10)//mid的mid次幂小于10,说明正确答案大于mid,则执行
        {
            l=mid;//使mid赋值给l,作为新的下限
        }
        else//否则,则执行
        {
            r=mid;//使mid赋值给r,作为新的上限
        }
    }
    JSZ=(int)(l*1000000+0.5);//最后是七位小数要四舍五入保留六位小数,故如此
    JSZ=JSZ/1000000;//最后得到四舍五入保留六位小数的近似值
    printf("%f\n",JSZ);//输出结果JSZ
    return 0;//返回0
}    
经过今天的垂死挣扎,总算是解决了这两道题,不对,是一道题两种解法,做题做失迷了,��,倍感欣慰,因为感觉自己每天都没有止步不前,我要继续努力,蓝桥杯a组才是我的第一个目标!