59

Math.Pow().NET中的内置函数将double基数提高到double指数并返回double结果。

对整数做同样的事情的最好方法是什么?

补充:似乎可以将Math.Pow()结果转换为(int),但这总是会产生正确的数字并且没有舍入错误吗?

4

10 回答 10

59

一个相当快的可能是这样的:

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

请注意,这不允许负幂。我会把它作为练习留给你。:)

补充:哦,是的,差点忘了——还要添加上溢/下溢检查,否则你可能会在路上遇到一些令人讨厌的惊喜。

于 2008-12-20T18:45:15.307 回答
53

LINQ有人吗?

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

用作扩展:

var threeToThePowerOfNine = 3.Pow(9);
于 2012-08-09T09:43:26.037 回答
21

使用约翰库克博客链接中的数学,

    public static long IntPower(int x, short power)
    {
        if (power == 0) return 1;
        if (power == 1) return x;
        // ----------------------
        int n = 15;
        while ((power <<= 1) >= 0) n--;

        long tmp = x;
        while (--n > 0)
            tmp = tmp * tmp * 
                 (((power <<= 1) < 0)? x : 1);
        return tmp;
    }           

解决如果您更改电源类型,代码将无法正常工作的反对意见,那么......撇开任何人更改他们不理解的代码然后在没有测试的情况下使用它......
但要解决问题,这个版本可以保护愚蠢的人免受那个错误的影响......(但不是他们可能犯的无数其他人)注意:未经测试。

    public static long IntPower(int x, short power)
    {
        if (power == 0) return 1;
        if (power == 1) return x;
        // ----------------------
        int n = 
            power.GetType() == typeof(short)? 15:
            power.GetType() == typeof(int)? 31:
            power.GetType() == typeof(long)? 63: 0;  

        long tmp = x;
        while (--n > 0)
            tmp = tmp * tmp * 
                 (((power <<= 1) < 0)? x : 1);
        return tmp;
    }

也试试这个递归等价物(当然更慢):

    public static long IntPower(long x, int power)
    {
        return (power == 0) ? x :
            ((power & 0x1) == 0 ? x : 1) *
                IntPower(x, power >> 1);
    }
于 2008-12-21T17:24:29.400 回答
12

怎么样:

public static long IntPow(long a, long b)
{
  long result = 1;
  for (long i = 0; i < b; i++)
    result *= a;
  return result;
}
于 2012-04-11T15:28:25.470 回答
5

非常有趣.. 从 .net 5.0 开始,SimplePower() 现在快了 350 倍。我会说在便携性/性能/可读性方面最好......

    public static int SimplePower(int x, int pow)
    {
        return (int)Math.Pow(x, pow);
    }

这是我过去建造的另一个速度很快的...

    public static int PowerWithSwitch(int x, int pow)
    {
        switch ((uint)pow)
        {
            case 0: return 1;
            case 1: return x;
            case 2: return x * x;
            case 3: return x * x * x;
            case 4: { int t2 = x * x; return t2 * t2; }
            case 5: { int t2 = x * x; return t2 * t2 * x; }
            case 6: { int t3 = x * x * x; return t3 * t3; }
            case 7: { int t3 = x * x * x; return t3 * t3 * x; }
            case 8: { int t3 = x * x * x; return t3 * t3 * x * x; }
            case 9: { int t3 = x * x * x; return t3 * t3 * t3; }
            case 10: { int t3 = x * x * x; return t3 * t3 * t3 * x; }
            case 11: { int t3 = x * x * x; return t3 * t3 * t3 * x * x; }
            case 12: { int t3 = x * x * x; return t3 * t3 * t3 * t3; }
            case 13: { int t3 = x * x * x; return t3 * t3 * t3 * t3 * x; }
            case 14: { int t4 = x * x * x * x; return t4 * t4 * t4 * x * x; }
            case 15: { int t4 = x * x * x * x; return t4 * t4 * t4 * x * x * x; }
            case 16: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4; }
            case 17: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * x; }
            case 18: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * x * x; }
            case 19: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * x * x * x; }
            case 20: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4; }
            case 21: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * x; }
            case 22: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * x * x; }
            case 23: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * x * x * x; }
            case 24: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * t4; }
            case 25: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * t4 * x; }
            case 26: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * t4 * x * x; }
            case 27: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * t4 * x * x * x; }
            case 28: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * t4 * t4; }
            case 29: { int t4 = x * x * x * x; return t4 * t4 * t4 * t4 * t4 * t4 * t4 * x; }
            default:
                if (x == 0)
                    return 0;
                else if (x == 1)
                    return 1;
                else
                    return (x % 1 == 0) ? int.MaxValue : int.MinValue;
        }
        return 0;
    }

性能测试(.Net 5)


  • MathPow(Sunsetquest):11 毫秒(.net 4 = 3693 毫秒)<- 350 倍快!!!

  • PowerWithSwitch(Sunsetquest): 145 毫秒 (.net 4 = 298 毫秒)

  • Vilx:148 毫秒(.net 4 = 320 毫秒)

  • Evan Moran 递归除法:249 毫秒(.net 4 = 644 毫秒)

  • 迷你我:288 毫秒(.net 4 = 194 毫秒)

  • Charles Bretana(又名库克):536 毫秒(.net 4 = 950 毫秒)

  • LINQ 版本:4416 毫秒(.net 4 = 3693 毫秒)

(测试说明:AMD Threadripper Gen1,.Net 4 & 5,发布版本,未附加调试器,基础:0-100k,exp:0-10)

注意:在上述测试中几乎没有进行准确性检查。

于 2014-02-13T06:49:38.110 回答
3

使用双版本,检查溢出(超过最大 int 或最大 long)并转换为 int 或 long?

于 2008-12-20T18:52:54.777 回答
2

对于这个问题,我最喜欢的解决方案是经典的分而治之的递归解决方案。它实际上比乘 n 次要快,因为它每次将乘法次数减少一半。

public static int Power(int x, int n)
{
  // Basis
  if (n == 0)
    return 1;
  else if (n == 1)
    return x;

  // Induction
  else if (n % 2 == 1)
    return x * Power(x*x, n/2);
  return Power(x*x, n/2);
}

注意:这不会检查溢出或负 n。

于 2011-07-01T22:25:22.483 回答
0

我将结果转换为 int,如下所示:

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

在这种情况下,没有舍入误差,因为基数和指数是整数。结果也将是整数。

于 2015-05-08T13:26:09.613 回答
0

对于一个简短的快速单线。

int pow(int i, int exp) => (exp == 0) ? 1 : i * pow(i, exp-1);

没有负指数也没有溢出检查。

于 2017-09-02T15:32:57.477 回答
0

另一种方法是:

int Pow(int value, int pow) {
    var result = value;
    while (pow-- > 1)
        result *= value;
    return pow == 0 ? result : pow == -1 ? 1 : throw new ArgumentOutOfRangeException(nameof(pow));
}
于 2020-06-09T12:14:35.927 回答