关于X开Y次方的算法

 前几天在CSDN上看到一个帖子:求X开Y次方的算法。我当时就回复了,当时的想法和做法还不完善,这几天我自己也一直在琢磨这个问题,同时把当时的想法和代码完善了一下,如下:
#include <math.h>
#include <stdio.h>
/*注意:此函数的默认前提是x>0,y>0且为整数,
 *函数中的精度参数ep并不表示结果的精度而是表示判断中间计算结果的精度。
 *函数的返回值是x开y次方的结果。
 *该算法致命的弱点是:如果y很大,那么由于这个算法是个双层
 *循环,会导致极大的循环量,非常耗时,计算出结果也会很慢很慢。
 *必须找出一种更好的验证方法!
 */
/*我自己发现可能有一种方法有可能减少循环次数:
 *将y分解因数,假设y=a*b*c,那么x开y次方,就可以将x先开
 *a次方,再将结果开b次方,再将结果开c次方。a,b,c的值越接近,
 *那么减少的循环次数会越多,效率会越高。但是对于很大的质数,这个
 *办法就无效了。可能存在的另外一个问题是,由于几次求值,可能导致
 *误差积累,使结果偏差很大。
 */
double x_sq_y(double x,unsigned int y)
{
  double s,root,b;
  double ep=1e-8;
  double ji;
  int small=0,big=0;
  unsigned int i;
  if(x<1.0) {s=x;b=1;root=(b+s)/2;ep=x*1e-8;}
  else {s=0;root=x/y;b=0;}
  /*这里对浮点数使用 != 号,是因为运算到了最后root和s,或者
   *root和b在double类型范围内计算机已经无法分辨其差别,所以
   *肯定会相等。
   */
  while(root != s && root != b){
    ji=1.0;
    i=0;
    while(i < y){
      ji*=root;
      i++;
      /*使用除法是为了防止乘法可能出现的溢出,这里的判断也是为了
       *不做无效的乘法计算,减少循环次数。
       */
      if((root>=1 && i <y &&((x+ep)/ji<root)) ||
         (root< 1 && i==y && ji>x+ep)) {
        big=1;
        b=root;
        if(small==0) root/=2;
        else root=(b+s)/2;
        break;
      }
      if((root>=1 && i==y && ji < x-ep) ||
         (root<1  && i <y &&(x-ep)/ji>root)) {
        small=1;
        s=root;
        if(big==0) root*=2;
        else root=(b+s)/2;
        break;
      }
      /*执行到了这里而且i==y,那么root必然就是要求的结果。*/
      if(i==y) return root;
    }
  }
  return root;
}

int main()
{
  double x;
  unsigned int y;
  int n;
  printf("这个程序计算x开y次方的结果,你需要输入x和y的值。/n");
  printf("注意:x>0,而且y为自然数。/n");
  while(1){
  input:
    n=scanf("%lf %u",&x,&y);
    if(x<=0 || y==0) goto input;
    if(n != 2) break;
    printf("pow(%G,%lf)=%.8lf/n",x,1.0/y,pow(x,1.0/y));
    printf("%G开%d次方结果=%.8lf /n",x,y,x_sq_y(x,y));
  }
  return 0;
}             
同时我还在思考,到底有什么方法可以更高效的将X开Y次方呢?
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值