回 帖 发 新 帖 刷新版面

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

声明:本来我自己准备了题目,但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个回复)

沙发

让更多的人参与,所以要顶!~~

板凳

//很常规的算法 但不能保证精度
//要注意0不能作底数

//VC++6.0

#include <stdio.h>

double power(double a, int n);

int main()
{
    double a;
    int n;
    scanf("%lf^%d",&a ,&n);
    printf("%G^%d=%G",a, n, power(a, n));//输出格式自动选择 屏蔽无效0
    return 0;
}

double power(double a, int n)
{
    double m = a;
    int i, c;

    if(n == 0)
        return 1.0;
    c = n < 0 ? -n : n;//正常处理负指数
    for(i = 1; i < c ; i++)
        m *= a;
    return n > 0 ? m : 1.0/m;
}
//输入格式 如10^100 或 20^-2

3 楼

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

void main() {
    double num;int n;
    printf("请输入数据和次方:\n");
    scanf("%lf%d",&num,&n);
    printf("结果=%lf\n",power(num,n));
    getchar();getchar();
}
编译环境:vc++6.0
使用语言:c
计算过程:采用递归形式

4 楼

函数中可以不考虑溢出问题。
什么意思, 不考虑高精吗?
unsigned long long的最大值是:

18446744073709551615

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

5 楼

//精度不能保证,
#include<iostream.h>
double power(double a, int n)
{
    long double b;
    if(n==0)
        b=1.0;
    else
    {
        for(b=1.0;n>0;n--)  //循环计算a的n次方
            b=b*a;
    }

    return b;
}
        
void main()
{
    int n;
    double a,c;
    cout<<"计算自然数的幂运算"<<endl;
    cout<<"请输入一个自然数:"<<endl;
    cin>>a;
    cout<<"请输入这个数的指数:"<<endl;
    cin>>n;
    c=power(a,n);
    cout<<a<<"的"<<n<<"次方为:"<<c<<endl;
}

6 楼

函数中可以不考虑溢出问题。
什么意思, 不考虑高精吗?
————————————————————
我的意思是如果计算100000的1000次方,明显超过了double的限制。在函数中这个不用考虑。

另外,大家只需要用double类型去做就可以了。这只是“普及型”的比赛,并不要求高精度计算。即使用了高精,返回值限死了为double,高精就高不起来了……
当然也可以尝试用高精,不过请自行修改返回类型以使程序功能完整。

7 楼

要提高效率,就是要减少乘法计算的次数,用空间来换时间:
如计算x的15次幂,先将指数15分解成8+4+2+1[2的N次方组合形式],然后分别计算
x^2 = x*x
x^4 = x^2*x^2
x^8 = x^4*x^4
因此
x^15=x^8*x^4*x^2*x^1;
这样是减少了乘法运算次数 但是还不是很好,因为分解指数要占用一定时间,而且分解后的运算次数还是比较多
有没有更好点的算法呢?
于是想到这样的方法:
求X^12340
将12340分解为10000+2*1000+3*100+4*10
为什么要这样转化呢?因为我们发现X的整十[或百千...]次方是很容易得到的


由于时间问题 暂只列出算法思想没写代码

8 楼

个人见解,在已经出现的解答中,2楼的明显要全面(考虑了指数为负的情况)和精简些。

如果我来做,暂时只有一个小地方可以改进,其它大同小异,就不贴了:

......

for(i = 1; i < c ; i++)

改为:

for (; c>=0; --c)

这样可以少引入一个变量i

......

9 楼

被LO几又VE指了出来。~~我的程序就是这样的。

#include <stdio.h>
#include <math.h>

double power(double a, int n)
{
    
    int m = (n > 0 ? n : -n);    // 对n的正负进行判断,以保证自乘次数正确
    
    int i;
    
    int count = 0;        // 这句是用来记录进行了几次相乘的。

    double s = 1;    // 这是要返回的结果。
    double r;
    
    if (n == 0)
    {
        return 1;
    }

    
    while (m > 0)    // 这里循环进行??次。
    {
        i = 1;
        r = a;
        
        // 这里的循环进行了log2(m)次。
        while ((i <<= 1) <= m)
        {
            r *= r;
            count++;
        }
        s *= r;
        m -= (i >> 1);
    }
    
    
    printf("count = %d\n", count);    // 如果不想要就删掉
    // 如果n是负数的话,应该取倒数再返回。
    return (n > 0 ? s : 1 / s);
}


// 提供了几组数字测试对比一下。
int main(void)
{
    double a;
    int n;
    
    
    a = 1.0, n = 0;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = 2.3, n = 30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = -2.3, n = 30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = 2.3, n = -30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = -2.3, n = -30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = 1235.125, n = 15;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = -1235.125, n = 15;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = 1235.125, n = -15;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = -1235.125, n = -15;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = 0.123, n = 30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = -0.123, n = 30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = 0.123, n = -30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    a = -0.123, n = -30;
    printf("power(%f, %d) = %f\n", a, n, power(a, n));
    printf("pow  (%f, %d) = %f\n", a, n, pow(a, n));
    
    return 0;
    
}

10 楼

/*********************************************************************************************/
/**     原创    随你整版  ********************************************************************/
/*********************************************************************************************/
#include <iostream.h>
#include <stdlib.h>
#include <string.h>

double EvenPower(double,int);
double OodPower(double,int);
double Power(double,int);
bool   IsNumber(char* s,bool IsFloat);
bool   IsNum(char c);

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

    cin>>inbuff;

    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=Power(a,n);
    cout<<"Ther result is:  "<<result<<endl;
    return 0;
}

bool IsNum(char c)   
{
    switch(c)
    {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
        return true;
    default:
        return false;
    }
}

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&&s[i]=='.')         //第一个字符不允许为小数点
            return false;
        if(i==0&&s[i]=='0'&&strlen(s)!=1)     //若为单个0,则可跳过,否则进如进行判断。
        {
            if(IsFloat==false)               //若不允许为小数,则第一个字符不允许为0
                return false;
            else
                if(s[i+1]!='.')        //若第一个字符为0,则第二个字符不允许再为数字。
                    return false;
        }
        else
        {
            if(!IsNum(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 OodPower(double a,int n)    //若n为奇数,执行次函数
{
    return a*EvenPower(a,n-1);    //提出一个底数,并调用n为偶数时的函数。
}

double Power(double a,int n)
{
    if(a==double(0.0))
        return 1.0;
    else if(n==0)
        return 1.0;
    else if(n%2==0)               //若为偶数
        return  EvenPower(a,n);
    else
        return  OodPower(a,n);
}

我来回复

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