主题:[讨论]第三次编程比赛题目
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个回复)
沙发
onasp [专家分:5600] 发布于 2005-10-28 19:41:00
让更多的人参与,所以要顶!~~
板凳
LO几又VE [专家分:14490] 发布于 2005-10-28 19:42:00
//很常规的算法 但不能保证精度
//要注意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 楼
Catamount3000 [专家分:7640] 发布于 2005-10-28 19:46:00
#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 楼
drizzlecrj1 [专家分:4230] 发布于 2005-10-28 19:56:00
函数中可以不考虑溢出问题。
什么意思, 不考虑高精吗?
unsigned long long的最大值是:
18446744073709551615
你给的参考数据显然有超出该值的。
参考数据:(利用windows自带计算器程序得出)
1.00001 的 10000 次方 = 1.1051703654940106069188996091683
123 的 50 次方 = 3.1279195318495243277303764742785e+104
0 的 0 次方 = 1
0.99999 的 10000 次方 = 0.90483696561434751400304156716182
5 楼
huahuagongzi [专家分:80] 发布于 2005-10-28 20:21:00
//精度不能保证,
#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 楼
eastcowboy [专家分:25370] 发布于 2005-10-28 20:29:00
函数中可以不考虑溢出问题。
什么意思, 不考虑高精吗?
————————————————————
我的意思是如果计算100000的1000次方,明显超过了double的限制。在函数中这个不用考虑。
另外,大家只需要用double类型去做就可以了。这只是“普及型”的比赛,并不要求高精度计算。即使用了高精,返回值限死了为double,高精就高不起来了……
当然也可以尝试用高精,不过请自行修改返回类型以使程序功能完整。
7 楼
LO几又VE [专家分:14490] 发布于 2005-10-28 20:41:00
要提高效率,就是要减少乘法计算的次数,用空间来换时间:
如计算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 楼
华山论剑 [专家分:5310] 发布于 2005-10-28 20:46:00
个人见解,在已经出现的解答中,2楼的明显要全面(考虑了指数为负的情况)和精简些。
如果我来做,暂时只有一个小地方可以改进,其它大同小异,就不贴了:
......
for(i = 1; i < c ; i++)
改为:
for (; c>=0; --c)
这样可以少引入一个变量i
......
9 楼
林杰杰 [专家分:8970] 发布于 2005-10-28 20:54:00
被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 楼
Jiff [专家分:640] 发布于 2005-10-28 21:20:00
/*********************************************************************************************/
/** 原创 随你整版 ********************************************************************/
/*********************************************************************************************/
#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);
}
我来回复