回 帖 发 新 帖 刷新版面

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

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

31 楼

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

32 楼

我再发一个

#include <stdio.h>

double power(double o_o,int h_h) {
    int T_T;double x_x;
    for (T_T=1,x_x=o_o;T_T++<((h_h<0)?-h_h:h_h);x_x*=o_o);
    return (h_h<0)?1.0/x_x:x_x;
}

void main() {
    double n_n;int w_w;
    scanf("%lf%d",&n_n,&w_w);
    printf("%lf",power(n_n,w_w));
    getchar();getchar();
}

33 楼

上面的函数改为
double EvenPower(double a, int n)
{
   double temp=Power(a,n/2);
      return temp*temp;
}

后效率提升了近一半多.呵呵
当初我也太马虎了,花了双倍的价值!

34 楼

我不参加比赛,但还是想发一下, 这个是O(log(N^2))的吧

#define BITWIDTH 15

double binpow (double a, int n)
{
        while (--n >= 0) a *= a;
        return a;
}

double log_power (double a, int n)
{
        int i, mask = 1;
        double s = 1.0;

        if (n == 0) return 1.0;
        if (n < 0) {a = 1.0 / a; n = -n;}
        for (i = 0; i < BITWIDTH; ++i, mask <<= 1)
                if (n & mask) s *= binpow (a, i);
        return s;
}

35 楼

上面算法不是logN的,[url=http://www.oioj.net/blog/user2/21189/archives/2005/170027.shtml]logN的[/url]就交给其他同学发表吧。

36 楼

#include "stdio.h"
double power(double a, int n)//n次方函数
{
    int i;
    double res=1;
    if (a==0)
        return 1;
    else
    {
    for(i=0;i<n;i++)
        res=res*a;//每次循环乘一次a
    return res;//返回函数的结果
    }
}
void main()
{
    double a;
    int n;
    printf("请您输入a的值:");//输入的值为要求n次方的数
    scanf("%lf",&a);
    printf("\n请您输入n的值:");//输入的值为多少次方
    scanf("%d",&n);
    printf("经过计算%lf的%d方是:%lf\n",a,n,power(a,n));    
}
//凑个热闹

37 楼

euc的代码注入了全新算法思路,不错。

有些朋友提到根据a的奇偶分别用不同的算法,当然,a如果是纯粹偶数可以用移位运算代替乘法提高效率。想法虽不错,可是实际上可能行不通。因为a是double值,范围很广,包含的小数部分就没有奇偶之说了。如果再加上整数/小数判断、奇偶判断,本来就增加了不小的运行开销,况且使代码结构复杂化,是不是有些得不偿失呢?

部分贴中我们不难看到很多直接或者变相抄2楼的地方。如果没有新东西,只是抄别人的,或者别人已经发了的,就别重复了,发了还不如不发的好!

我这个人喜欢说实话,别人不敢说或者不好说的就由我来说吧!砖头、谩骂尽管向我身上招呼。

38 楼

#include<stdio.h>

double Power(double a, int n);

int main()
{
    double a, result;
    int n;

    printf("please input a :");
    scanf("%lf",&a);

    printf("please input n:");
    scanf("%d",&n);
    
    result = Power(a, n);
    printf("%lf",result);
    
    return 0;
}
double Power(double a, int n)
{
    double r = 1; //存放奇数次幂的积
    double b = a; //存放偶数次幂
    int i;  //循环次数

    if(n == 0)
        return 1.0;
    else
    if(n < 0)
        n = -n;

    i = n;
    while(i > 1)
    {
        if(i % 2 ==0) /*偶次方*/
        {
            b = b * b;
            i = i / 2;
        }
        else    
        {
            r = r * b;
            i--;
        }
    }
    if(n < 0)
        return 1 / (r * b);
    else
        return r * b;
}


39 楼

好像已经有人贴过log n的了吧?我晚了...

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

double Power(double a, int n)
{
    // O(log n)
    double t, s = 1;
    if (n < 0)
        t = 1. / a, n = -n;
    else
        t = a;
    for (; n; n >>= 1)
    {
        if (n & 1)
            s *= t;
        t *= t;
    }
    return s;
}

int main()
{
    double a;
    int n;
    while(scanf("%lf%d", &a, &n)==2)
    {
        printf("%lf^%d=\n%lf\n%lf\n", a, n, Power(a, n), pow(a, n));
    }
    return 0;
}

/// btw. 有的人愿意看这样的代码...那么也顺便满足一下好了
double Power(double a, int n)
{
    // O(log n)
    double s = 1;

    for (n < 0 && (a = 1. / a, n = -n); n; n >>= 1, a *= a)
        n & 1 && (s *= a);

    return s;
}

40 楼

另一个方法:
前面log n的方法其实具体的运算量在log n到2 * log n之间。比如对18,用log n的方法有6次乘法:
18 = 10010 //包括4次进位的a *= a和2次s *= a
而这样分:
18=3*3*2
a2=a*a
a6=a2*a2*a2
a18=a6*a6*a6
或者:
a3 = a*a*a
a6 = a3*a3
a18=a6*a6*a6
就只要5次乘法。
具体方法是对n分解质因数。把问题降为多个求幂的小问题。(这个角度来看有点像jiff分奇偶那个程序)
对每个小问题,分别再使用一个logn的方法。

看上去这个问题对这个题目并没有帮助,反而多了一个因数分解的过程。
不过对高精度乘法来说,分解低精度整数n的过程是划算的。减少的高精度乘法次数还是比较可观的:)

[color=FF0000]等等,第二个方法复杂度更高...各位,我错了:([/color]

我来回复

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