C 负指数平方幂

C 负指数平方幂,c,algorithm,math,recursion,C,Algorithm,Math,Recursion,我不确定平方幂是否考虑负指数。我实现了以下代码,它只适用于正数 #include <stdio.h> int powe(int x, int exp) { if (x == 0) return 1; if (x == 1) return x; if (x&1) return powe(x*x, exp/2);

我不确定平方幂是否考虑负指数。我实现了以下代码,它只适用于正数

    #include <stdio.h>
    int powe(int x, int exp)
    {
         if (x == 0)
            return 1;
         if (x == 1)
            return x;
         if (x&1)
                return powe(x*x, exp/2);
         else
                return x*powe(x*x, (exp-1)/2);       
    }
#包括
整数功率(整数x,整数exp)
{
如果(x==0)
返回1;
如果(x==1)
返回x;
如果(x&1)
返回功率(x*x,exp/2);
其他的
返回x*功率(x*x,(exp-1)/2);
}
查看没有帮助,因为下面的代码似乎是错误的

    Function exp-by-squaring(x, n ) 
      if n < 0  then return exp-by-squaring(1 / x, - n );
      else if n = 0  then return  1;
      else if n = 1  then return  x ; 
      else if n is even  then return exp-by-squaring(x * x,  n / 2);
      else if n is odd  then return x * exp-by-squaring(x * x, (n - 1) / 2).
平方函数exp(x,n)
如果n<0,则通过平方(1/x,-n)返回exp;
否则,如果n=0,则返回1;
否则,如果n=1,则返回x;
否则,如果n为偶数,则通过平方(x*x,n/2)返回exp;
否则,如果n是奇数,则通过平方(x*x,(n-1)/2)返回x*exp。
编辑: 由于amit,此解决方案适用于负数和正数:

    float powe(float x, int exp)
    {
            if (exp < 0)
                    return powe(1/x, -exp);
            if (exp == 0)
                    return 1;
            if (exp == 1)
                    return x;
            if (((int)exp)%2==0)
                    return powe(x*x, exp/2);
            else
                    return x*powe(x*x, (exp-1)/2);
    }
float功率(float x,int exp)
{
如果(exp<0)
返回功率(1/x,-exp);
如果(exp==0)
返回1;
如果(exp==1)
返回x;
如果((int)exp)%2==0)
返回功率(x*x,exp/2);
其他的
返回x*功率(x*x,(exp-1)/2);
}
对于分数指数,我们可以执行以下操作(Spektre方法):

  • 假设你有x^0.5,那么你可以很容易地用这个方法计算平方根:从0开始到x/2,并不断检查x^2是否等于结果


  • 因此,如果有x^(1/3),则必须替换
    ,如果mid*mid整数示例用于32位
    int
    算术,
    DWORD
    是32位
    无符号int

  • 浮动
    pow(x,y)=x^y

    通常是这样评估的:

    //---------------------------------------------------------------------------
    //--- 32bit signed fixed point format (2os complement)
    //---------------------------------------------------------------------------
    // |MSB              LSB|
    // |integer|.|fractional|
    //---------------------------------------------------------------------------
    const int _fx32_bits=32;                                // all bits count
    const int _fx32_fract_bits=16;                          // fractional bits count
    const int _fx32_integ_bits=_fx32_bits-_fx32_fract_bits; // integer bits count
    //---------------------------------------------------------------------------
    const int _fx32_one       =1<<_fx32_fract_bits;         // constant=1.0 (fixed point)
    const float _fx32_onef    =_fx32_one;                   // constant=1.0 (floating point)
    const int _fx32_fract_mask=_fx32_one-1;                 // fractional bits mask
    const int _fx32_integ_mask=0xFFFFFFFF-_fx32_fract_mask; // integer bits mask
    const int _fx32_sMSB_mask =1<<(_fx32_bits-1);           // max signed bit mask
    const int _fx32_uMSB_mask =1<<(_fx32_bits-2);           // max unsigned bit mask
    //---------------------------------------------------------------------------
    float fx32_get(int   x) { return float(x)/_fx32_onef; }
    int   fx32_set(float x) { return int(float(x*_fx32_onef)); }
    //---------------------------------------------------------------------------
    int fx32_mul(const int &x,const int &y) // x*y
        {
        int a=x,b=y;                // asm has access only to local variables
        asm {                       // compute (a*b)>>_fx32_fract
            mov eax,a
            mov ebx,b
            mul eax,ebx             // (edx,eax)=a*b
            mov ebx,_fx32_one
            div ebx                 // eax=(a*b)>>_fx32_fract
            mov a,eax;
            }
        return a;
        }
    //---------------------------------------------------------------------------
    int fx32_div(const int &x,const int &y) // x/y
        {
        int a=x,b=y;                // asm has access only to local variables
        asm {                       // compute (a*b)>>_fx32_fract
            mov eax,a
            mov ebx,_fx32_one
            mul eax,ebx             // (edx,eax)=a<<_fx32_fract
            mov ebx,b
            div ebx                 // eax=(a<<_fx32_fract)/b
            mov a,eax;
            }
        return a;
        }
    //---------------------------------------------------------------------------
    int fx32_abs_sqrt(int x)            // |x|^(0.5)
        {
        int m,a;
        if (!x) return 0;
        if (x<0) x=-x;
        m=bits(x);                  // integer bits
        for (a=x,m=0;a;a>>=1,m++);  // count all bits
        m-=_fx32_fract_bits;        // compute result integer bits (half of x integer bits)
        if (m<0) m=0; m>>=1;
        m=_fx32_one<<m;             // MSB of result mask
        for (a=0;m;m>>=1)           // test bits from MSB to 0
            {
            a|=m;                   // bit set
            if (fx32_mul(a,a)>x)    // if result is too big
             a^=m;                  // bit clear
            }
        return a;
        }
    //---------------------------------------------------------------------------
    int fx32_pow(int x,int y)       // x^y
        {
        // handle special cases
        if (!y) return _fx32_one;                           // x^0 = 1
        if (!x) return 0;                                   // 0^y = 0  if y!=0
        if (y==-_fx32_one) return fx32_div(_fx32_one,x);    // x^-1 = 1/x
        if (y==+_fx32_one) return x;                        // x^+1 = x
        int m,a,b,_y; int sx,sy;
        // handle the signs
        sx=0; if (x<0) { sx=1; x=-x; }
        sy=0; if (y<0) { sy=1; y=-y; }
        _y=y&_fx32_fract_mask;      // _y fractional part of exponent
         y=y&_fx32_integ_mask;      //  y integer part of exponent
        a=_fx32_one;                // ini result
        // powering by squaring x^y
        if (y)
            {
            for (m=_fx32_uMSB_mask;(m>_fx32_one)&&(m>y);m>>=1);     // find mask of highest bit of exponent
            for (;m>=_fx32_one;m>>=1)
                {
                a=fx32_mul(a,a);
                if (int(y&m)) a=fx32_mul(a,x);
                }
            }
        // powering by rooting x^_y
        if (_y)
            {
            for (b=x,m=_fx32_one>>1;m;m>>=1)                            // use only fractional part
                {
                b=fx32_abs_sqrt(b);
                if (int(_y&m)) a=fx32_mul(a,b);
                }
            }
        // handle signs
        if (sy) { if (a) a=fx32_div(_fx32_one,a); else a=0; /*Error*/ }     // underflow
        if (sx) { if (_y) a=0; /*Error*/ else if(int(y&_fx32_one)) a=-a; }  // negative number ^ non integer exponent, here could add test if 1/_y is integer instead
        return a;
        }
    //---------------------------------------------------------------------------
    
    float a,b,c0,c1,d;
    int x,y;
    for (a=0.0,x=fx32_set(a);a<=10.0;a+=0.1,x=fx32_set(a))
     for (b=-2.5,y=fx32_set(b);b<=2.5;b+=0.1,y=fx32_set(b))
        {
        if (!x) continue; // math pow has problems with this
        if (!y) continue; // math pow has problems with this
        c0=pow(a,b);
        c1=fx32_get(fx32_pow(x,y));
        d=0.0;
        if (fabs(c1)<1e-3) d=c1-c0; else d=(c0/c1)-1.0;
        if (fabs(d)>0.1)
         d=d; // here add breakpoint to check inconsistencies with math pow
        }
    
    因此可以计算分数指数:
    pow(x,y)=exp2(y*log2(x))
    。这也可以在固定点上完成:

  • 整数
    pow(a,b)=a^b
    其中
    a>=0,b>=0

    这很容易(您已经做到了)通过平方:

        DWORD powuu(DWORD a,DWORD b)
            {   
            int i,bits=32;
            DWORD d=1;
            for (i=0;i<bits;i++)
                {
                d*=d;
                if (DWORD(b&0x80000000)) d*=a;
                b<<=1;
                }
            return d;
            }
    
  • 整数
    pow(a,b)=a^b

    所以如果
    bx)
    if(pow(a,bb)>x)
    其中
    bb=1/b
    。。。所以
    b
    是您要查找的分数指数,
    bb
    是整数。另外
    m
    是结果的位数,因此改变
    m=(位(x)>>1)
    m=(位(x)/bb)

  • [edit1]定点sqrt示例

    //---------------------------------------------------------------------------
    const int _fx32_fract=16;       // fractional bits count
    const int _fx32_one  =1<<_fx32_fract;
    DWORD fx32_mul(const DWORD &x,const DWORD &y)   // unsigned fixed point mul
        {
        DWORD a=x,b=y;              // asm has access only to local variables
        asm {                       // compute (a*b)>>_fx32_fract
            mov eax,a               // eax=a
            mov ebx,b               // ebx=b
            mul eax,ebx             // (edx,eax)=eax*ebx
            mov ebx,_fx32_one
            div ebx                 // eax=(edx,eax)>>_fx32_fract
            mov a,eax;
            }
        return a;
        }
    DWORD fx32_sqrt(const DWORD &x) // unsigned fixed point sqrt
        {
        DWORD m,a;
        if (!x) return 0;
        m=bits(x);                  // integer bits
        if (m>_fx32_fract) m-=_fx32_fract; else m=0;
        m>>=1;                      // sqrt integer result is half of x integer bits
        m=_fx32_one<<m;             // MSB of result mask
        for (a=0;m;m>>=1)           // test bits from MSB to 0
            {
            a|=m;                   // bit set
            if (fx32_mul(a,a)>x)    // if result is too big
             a^=m;                  // bit clear
            }
        return a;
        }
    //---------------------------------------------------------------------------
    
    我对它进行了如下测试:

    //---------------------------------------------------------------------------
    //--- 32bit signed fixed point format (2os complement)
    //---------------------------------------------------------------------------
    // |MSB              LSB|
    // |integer|.|fractional|
    //---------------------------------------------------------------------------
    const int _fx32_bits=32;                                // all bits count
    const int _fx32_fract_bits=16;                          // fractional bits count
    const int _fx32_integ_bits=_fx32_bits-_fx32_fract_bits; // integer bits count
    //---------------------------------------------------------------------------
    const int _fx32_one       =1<<_fx32_fract_bits;         // constant=1.0 (fixed point)
    const float _fx32_onef    =_fx32_one;                   // constant=1.0 (floating point)
    const int _fx32_fract_mask=_fx32_one-1;                 // fractional bits mask
    const int _fx32_integ_mask=0xFFFFFFFF-_fx32_fract_mask; // integer bits mask
    const int _fx32_sMSB_mask =1<<(_fx32_bits-1);           // max signed bit mask
    const int _fx32_uMSB_mask =1<<(_fx32_bits-2);           // max unsigned bit mask
    //---------------------------------------------------------------------------
    float fx32_get(int   x) { return float(x)/_fx32_onef; }
    int   fx32_set(float x) { return int(float(x*_fx32_onef)); }
    //---------------------------------------------------------------------------
    int fx32_mul(const int &x,const int &y) // x*y
        {
        int a=x,b=y;                // asm has access only to local variables
        asm {                       // compute (a*b)>>_fx32_fract
            mov eax,a
            mov ebx,b
            mul eax,ebx             // (edx,eax)=a*b
            mov ebx,_fx32_one
            div ebx                 // eax=(a*b)>>_fx32_fract
            mov a,eax;
            }
        return a;
        }
    //---------------------------------------------------------------------------
    int fx32_div(const int &x,const int &y) // x/y
        {
        int a=x,b=y;                // asm has access only to local variables
        asm {                       // compute (a*b)>>_fx32_fract
            mov eax,a
            mov ebx,_fx32_one
            mul eax,ebx             // (edx,eax)=a<<_fx32_fract
            mov ebx,b
            div ebx                 // eax=(a<<_fx32_fract)/b
            mov a,eax;
            }
        return a;
        }
    //---------------------------------------------------------------------------
    int fx32_abs_sqrt(int x)            // |x|^(0.5)
        {
        int m,a;
        if (!x) return 0;
        if (x<0) x=-x;
        m=bits(x);                  // integer bits
        for (a=x,m=0;a;a>>=1,m++);  // count all bits
        m-=_fx32_fract_bits;        // compute result integer bits (half of x integer bits)
        if (m<0) m=0; m>>=1;
        m=_fx32_one<<m;             // MSB of result mask
        for (a=0;m;m>>=1)           // test bits from MSB to 0
            {
            a|=m;                   // bit set
            if (fx32_mul(a,a)>x)    // if result is too big
             a^=m;                  // bit clear
            }
        return a;
        }
    //---------------------------------------------------------------------------
    int fx32_pow(int x,int y)       // x^y
        {
        // handle special cases
        if (!y) return _fx32_one;                           // x^0 = 1
        if (!x) return 0;                                   // 0^y = 0  if y!=0
        if (y==-_fx32_one) return fx32_div(_fx32_one,x);    // x^-1 = 1/x
        if (y==+_fx32_one) return x;                        // x^+1 = x
        int m,a,b,_y; int sx,sy;
        // handle the signs
        sx=0; if (x<0) { sx=1; x=-x; }
        sy=0; if (y<0) { sy=1; y=-y; }
        _y=y&_fx32_fract_mask;      // _y fractional part of exponent
         y=y&_fx32_integ_mask;      //  y integer part of exponent
        a=_fx32_one;                // ini result
        // powering by squaring x^y
        if (y)
            {
            for (m=_fx32_uMSB_mask;(m>_fx32_one)&&(m>y);m>>=1);     // find mask of highest bit of exponent
            for (;m>=_fx32_one;m>>=1)
                {
                a=fx32_mul(a,a);
                if (int(y&m)) a=fx32_mul(a,x);
                }
            }
        // powering by rooting x^_y
        if (_y)
            {
            for (b=x,m=_fx32_one>>1;m;m>>=1)                            // use only fractional part
                {
                b=fx32_abs_sqrt(b);
                if (int(_y&m)) a=fx32_mul(a,b);
                }
            }
        // handle signs
        if (sy) { if (a) a=fx32_div(_fx32_one,a); else a=0; /*Error*/ }     // underflow
        if (sx) { if (_y) a=0; /*Error*/ else if(int(y&_fx32_one)) a=-a; }  // negative number ^ non integer exponent, here could add test if 1/_y is integer instead
        return a;
        }
    //---------------------------------------------------------------------------
    
    float a,b,c0,c1,d;
    int x,y;
    for (a=0.0,x=fx32_set(a);a<=10.0;a+=0.1,x=fx32_set(a))
     for (b=-2.5,y=fx32_set(b);b<=2.5;b+=0.1,y=fx32_set(b))
        {
        if (!x) continue; // math pow has problems with this
        if (!y) continue; // math pow has problems with this
        c0=pow(a,b);
        c1=fx32_get(fx32_pow(x,y));
        d=0.0;
        if (fabs(c1)<1e-3) d=c1-c0; else d=(c0/c1)-1.0;
        if (fabs(d)>0.1)
         d=d; // here add breakpoint to check inconsistencies with math pow
        }
    
    浮点a、b、c0、c1、d;
    int x,y;
    
    对于(a=0.0,x=fx32_set(a);a您认为这是错误的吗?第二个代码实际上处理负指数问题,因为
    x^n=(x^-1)^(-n)
    -@amit:终止条件是什么?我对这个解决方案进行了编码,它在负指数的无限循环中运行。第一个代码确实没有考虑负指数的行为。但是第二个代码是正确的,尽管你说它“似乎错了”我的问题是:为什么第二个代码对你来说似乎是错误的?我之所以提到它是因为
    x^n=(x^-1)^(-n)
    @amit:你能澄清一下哪个是“第一个代码”,哪个是“第二个代码”吗你指的是这里?@FalconUA:是的,愚蠢的错误,我想做exp&1来检查奇数。s:请解释更多分数?@newbie\u old你知道二进制搜索是如何工作的吗(例如sqrt?)@新手添加了sqrt二进制搜索的旧代码,并提示要更改的内容…如果不够,请评论我,我将编写一些代码,但不是现在,我需要工作几小时Spektre:是,从0开始到x/2,并不断检查x^2是否等于二进制搜索中的数字method@newbie_old因此,您不必检查
    x^bb
    x^(1/b)
    其中
    bb=1/b
    因此使用整数指数。但从MSB位开始,逐位移位,因此只检查位(x)/bb次(二进制搜索,而不是线性搜索)
    float a,b,c0,c1,d;
    int x,y;
    for (a=0.0,x=fx32_set(a);a<=10.0;a+=0.1,x=fx32_set(a))
     for (b=-2.5,y=fx32_set(b);b<=2.5;b+=0.1,y=fx32_set(b))
        {
        if (!x) continue; // math pow has problems with this
        if (!y) continue; // math pow has problems with this
        c0=pow(a,b);
        c1=fx32_get(fx32_pow(x,y));
        d=0.0;
        if (fabs(c1)<1e-3) d=c1-c0; else d=(c0/c1)-1.0;
        if (fabs(d)>0.1)
         d=d; // here add breakpoint to check inconsistencies with math pow
        }