主题:[讨论]第三次编程比赛题目
eastcowboy
[专家分:25370] 发布于 2005-10-28 19:30:00
声明:本来我自己准备了题目,但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 楼
林杰杰 [专家分:8970] 发布于 2005-10-28 23:57:00
上面的居然写错了……[em8]应该是O(log2(m)的平方)才对。[em8]谢谢euc提醒。
22 楼
eastcowboy [专家分:25370] 发布于 2005-10-29 00:29:00
我都写了两种方案了,复杂度都是 O(log(n))。
同志们加油啊~~
23 楼
Catamount3000 [专家分:7640] 发布于 2005-10-29 00:38:00
这次修改一下,即使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 楼
eastcowboy [专家分:25370] 发布于 2005-10-29 00:46:00
catamount3000:还是不对。
power(2,-2)结果为4,正确结果为0.25
唔,后来改好了~~
26 楼
littleking [专家分:30] 发布于 2005-10-29 09:08:00
#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 楼
littleking [专家分:30] 发布于 2005-10-29 09:10:00
#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 楼
Jiff [专家分:640] 发布于 2005-10-29 09:42:00
我晕~~~~
我可不想得效率最差奖啊!
嗨!谁叫我没看中效率了,呵呵!
大概是频繁的函数调用损了
不少效率,本来是想使代码更
易读,且保留重用度的.还有
我只所以不掉用isdigit()函数而
自己编是因为我不想因为一个简单
函数而需增加一个ctype.h头文件.
不知楼主有没有考虑这些因数作为
评判的标准.
我没想到4秒算出1.000001的10000000次方
竟然是效率最低的.
不愧是高手如云啊~~~呵呵
29 楼
Jiff [专家分:640] 发布于 2005-10-29 10:05:00
/*********************************************************************************************/
/** 原创 真正的随你整版 除去了随你整版中的指数不能为负的情况***************************/
/**********改进,代码更短,效率更高!若效率还是最差,你就毙了我!*****************************/
#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 楼
eastcowboy [专家分:25370] 发布于 2005-10-29 10:47:00
Jiff:
好,进步了,不过还没有抓住最关键的环节。请继续。
我来回复