How do you do *integer* exponentiation in C#?

前端 未结 11 1026
迷失自我
迷失自我 2020-11-30 08:26

The built-in Math.Pow() function in .NET raises a double base to a double exponent and returns a double result.

W

相关标签:
11条回答
  • 2020-11-30 08:48

    I cast the result into int, like this:

    double exp = 3.0;
    int result = (int)Math.Pow(2.0, exp);
    

    In this case, there are no rounding errors because base and exponent are integer. The result will be integer too.

    0 讨论(0)
  • Here's a blog post that explains the fastest way to raise integers to integer powers. As one of the comments points out, some of these tricks are built into chips.

    0 讨论(0)
  • 2020-11-30 08:55

    A pretty fast one might be something like this:

    int IntPow(int x, uint pow)
    {
        int ret = 1;
        while ( pow != 0 )
        {
            if ( (pow & 1) == 1 )
                ret *= x;
            x *= x;
            pow >>= 1;
        }
        return ret;
    }
    

    Note that this does not allow negative powers. I'll leave that as an exercise to you. :)

    Added: Oh yes, almost forgot - also add overflow/underflow checking, or you might be in for a few nasty surprises down the road.

    0 讨论(0)
  • 2020-11-30 08:59

    LINQ anyone?

    public static int Pow(this int bas, int exp)
    {
        return Enumerable
              .Repeat(bas, exp)
              .Aggregate(1, (a, b) => a * b);
    }
    

    usage as extension:

    var threeToThePowerOfNine = 3.Pow(9);
    
    0 讨论(0)
  • 2020-11-30 09:00

    Two more...

        public static int FastPower(int x, int pow)
        {
            switch (pow)
            {
                case 0: return 1;
                case 1: return x;
                case 2: return x * x;
                case 3: return x * x * x;
                case 4: return x * x * x * x;
                case 5: return x * x * x * x * x;
                case 6: return x * x * x * x * x * x;
                case 7: return x * x * x * x * x * x * x;
                case 8: return x * x * x * x * x * x * x * x;
                case 9: return x * x * x * x * x * x * x * x * x;
                case 10: return x * x * x * x * x * x * x * x * x * x; 
                case 11: return x * x * x * x * x * x * x * x * x * x * x; 
                // up to 32 can be added 
                default: // Vilx's solution is used for default
                    int ret = 1;
                    while (pow != 0)
                    {
                        if ((pow & 1) == 1)
                            ret *= x;
                        x *= x;
                        pow >>= 1;
                    }
                    return ret;
            }
        }
    
        public static int SimplePower(int x, int pow)
        {
            return (int)Math.Pow(x, pow);
        }
    

    I did some quick performance testing


    • mini-me : 32 ms

    • Sunsetquest(Fast) : 37 ms

    • Vilx : 46 ms

    • Charles Bretana(aka Cook's): 166 ms

    • Sunsetquest(simple) : 469 ms

    • 3dGrabber (Linq version) : 868 ms

    (testing notes: intel i7 2nd gen, .net 4, release build, release run, 1M different bases, exp from 0-10 only)

    Conclusion: mini-me's is the best in both performance and simplicity

    very minimal accuracy testing was done

    0 讨论(0)
  • 2020-11-30 09:06

    How about:

    public static long IntPow(long a, long b)
    {
      long result = 1;
      for (long i = 0; i < b; i++)
        result *= a;
      return result;
    }
    
    0 讨论(0)
提交回复
热议问题