回 帖 发 新 帖 刷新版面

主题:[讨论]第三次编程比赛题目

声明:本来我自己准备了题目,但euc又给了我一个题目。在比较之后我认为他的题目更适合目前的比赛。(原来题目不怎么严密,所以我适当修改了一下。)

请大家给euc鼓掌,呵呵

题目描述如下:
请编写一个函数(C/C++都可以),其原型为:
double power(double a,int n);
实现在double范围内计算a的n次方,并返回计算结果,函数中可以不考虑溢出问题。
另行编写main函数以及其他任何必要的函数,使程序结构完整,最好能在程序中一定程度上验证自己的函数。
请尽量注意程序的严谨性、效率、代码风格等因素。这些将作为产生冠军的参考条件。

说明:
本题目不是考察大家是否知道pow这个函数~~
请大家不要使用pow函数。(当然了,用于检验的时候还是可以的。)

参考数据:(利用windows自带计算器程序得出)
1.00001 的 10000 次方  =  1.1051703654940106069188996091683
    123 的    50 次方  =  3.1279195318495243277303764742785e+104
      0 的     0 次方  =  1
0.99999 的 10000 次方  =  0.90483696561434751400304156716182



再次重申比赛的一些原则:
1、请仔细思考,编程然后帖上自己的代码。不要帖别人现成的东西,那样没什么意思。
2、请认真对待题目,帖上自己认为正确的代码,不要帖有明显逻辑错误甚至语法错误的代码。(至少应该要通过编译吧)
3、请注明自己使用的语言、编译器/编译环境。比较有特色的程序请写一个简短的介绍。(当然比较一般的程序也可以写介绍)
4、建议:程序要有注释。
5、请文明参赛,不要在比赛时做出任何恶意行为。
6、本人将对本次比赛规则保留解释权^-^

比赛从28日(星期五)晚上7点30分持续到29日(星期六)晚上11点30分,共28小时,希望大家都能找到自己合适的时间来答题。

好了,我的废话完毕。
大家加油吧!

回复列表 (共46个回复)

21 楼

上面的居然写错了……[em8]应该是O(log2(m)的平方)才对。[em8]谢谢euc提醒。

22 楼

我都写了两种方案了,复杂度都是 O(log(n))。
同志们加油啊~~

23 楼

这次修改一下,即使n为负数也不会出错

#include <stdio.h>
double power(double a,int n) {
    int c=(n<0)?-n:n;
    double m;
    if (n==0) return 1.0;
    m=a*power(a,c-1);
    return (n>0)?m:1.0/m;
}

void main() {
    double num;int n;
    printf("请输入数据和次方:\n");
    scanf("%lf%d",&num,&n);
    printf("结果=%lf\n",power(num,n));
    getchar();getchar();
}

24 楼

catamount3000:还是不对。
power(2,-2)结果为4,正确结果为0.25

唔,后来改好了~~

25 楼

现在应该已经改好了吧

26 楼

#include <stdio.h>
long double power( );//函数的原形说明。

void main()
{
    float a;
    int m;
    long double t;
    scanf("%f,%d",&a,&m);
    t=power(&a,&m);//用数据的地址来传递到函数中。
    printf("%lf\n",t);
    getchar();
}


long double power(float *b,int *s)
{
    long double r;
    int j,c;
    r=(*b);
     if((*s)==0) return 1;
    (*s)<0? (c=(-(*s))):(c=(*s));
    for(j=1;j<c;j++)
    {
         r*=(*b);
    }
    if((*s)<0)  return 1.0/r;
     else       return  r;
}

27 楼

#include <stdio.h>
long double power( );//函数的原形说明。

void main()
{
    float a;
    int m;
    long double t;
    scanf("%f,%d",&a,&m);
    t=power(&a,&m);//用数据的地址来传递到函数中。
    printf("%lf\n",t);
    getchar();
}


long double power(float *b,int *s)
{
    long double r;
    int j,c;
    r=(*b);
     if((*s)==0) return 1;
    (*s)<0? (c=(-(*s))):(c=(*s));
    for(j=1;j<c;j++)
    {
         r*=(*b);
    }
    if((*s)<0)  return 1.0/r;
     else       return  r;
}


28 楼

我晕~~~~
我可不想得效率最差奖啊!
嗨!谁叫我没看中效率了,呵呵!
大概是频繁的函数调用损了
不少效率,本来是想使代码更
易读,且保留重用度的.还有
我只所以不掉用isdigit()函数而
自己编是因为我不想因为一个简单
函数而需增加一个ctype.h头文件.

不知楼主有没有考虑这些因数作为
评判的标准.
我没想到4秒算出1.000001的10000000次方
竟然是效率最低的.
不愧是高手如云啊~~~呵呵

29 楼

/*********************************************************************************************/
/**     原创    真正的随你整版 除去了随你整版中的指数不能为负的情况***************************/
/**********改进,代码更短,效率更高!若效率还是最差,你就毙了我!*****************************/
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

double EvenPower(double,int);
double Power(double,int);
bool   IsNumber(char* s,bool IsFloat);  //第三个参数用于判断数字是整数还是浮点数,有重用价值。

int main()
{
    cout<<"Please input a number:"<<endl;
    char  inbuff[50];
    double a;
    
    inbuff[0]='\0';

    cin>>inbuff;
    bool IsAbove0=true;
    bool IsAbove1=true;             //默认时基数与指数均为正数.
    while(!IsNumber(inbuff,true))    
    {
        cout<<"The number is Invalid,Please input again:"<<endl;
        cin>>inbuff;
    }
    a=atof(inbuff);
    cout<<"And then input a number of int type:"<<endl;
    int n;
    
    inbuff[0]='\0';
    
    cin>>inbuff;

    while(!IsNumber(inbuff,false))
    {
        cout<<"The number is Invalid,Please input again:"<<endl;
        cin>>inbuff;
    }

    n=atoi(inbuff);

    double result;
    if(n>=0)
        result=Power(a,n);
    else
        result=Power(a,-n);

    bool IsInvert=false;    //IsLarge 用于判断结果的正负,
                           //IsInvert用于判断结果是否需要作为1/result的形式。
    if(n<0)
        IsInvert=true;
    cout<<"The result is  ";
    if(IsInvert)
        result=1.0/result;
    cout<<result<<endl;
    return 0;
}
bool IsNumber(char* s,bool IsFloat)       //若允许输入小数,则IsFloat为true,否则为false
{  
      bool HaveDot=false;         //用于标记是否存在小数点
    for(int i=0;i<strlen(s);++i)    //刚开初我为了少调用一个string.h文件,此处用的是sizeof(s),但
                    //就是运行错误,换成sizeof(s)-1也一样,没办法,只好用strlen(s),希望各位帮我分析一下为什么。
    {
       if(i==0)
     {
            if(s[i]=='.')         //第一个字符不允许为小数点
                 return false;
        if(s[i]=='0'&&strlen(s)!=1)     //若为单个0,则可跳过,否则进如进行判断。
        {
            if(IsFloat==false)               //若不允许为小数,则第一个字符不允许为0
                return false;
            else
                if(s[i+1]!='.')        //若第一个字符为0,则第二个字符不允许再为数字。
                    return false;
        }
     }
        else
        {
            if(!isdigit(s[i]))             //若本字符不是数字
            {
                if(IsFloat==false)         //若该数不允许为小数,则直接返回false
                    return false;
                else
                {
                    if(s[i]=='.'&&HaveDot==false)   //若该字符为第一次出现的小数点,则更改
                                                    //小数点状态为已存在小数点
                    {
                        HaveDot=true;
                        continue;
                    }
                    else                          //否则,返回false
                        return false;
                }
            }
            else
                continue;
        }
    }
    return true;
}

double EvenPower(double a,int n)    //若n为偶数,执行次函数
{
    return Power(a,n/2)*Power(a,n/2);    //折半递归进行
}

double Power(double a,int n)
{
    if(a==double(0.0)||n==0)
        return 1.0;
    else if(n%2==0)               //若为偶数
        return  EvenPower(a,n);
    else
        return  a*EvenPower(a,n-1);
}
//算1.000001的10000000次方为3秒,提升1秒,且代码减少.
//先前少了根茎,多写了那么多代码.

30 楼

Jiff:
好,进步了,不过还没有抓住最关键的环节。请继续。

我来回复

您尚未登录,请登录后再回复。点此登录或注册