你如何做*整数*在C#中指数?

.NET中内build的Math.Pow()函数将double Math.Pow()指数提升为double Math.Pow()并返回double Math.Pow()结果。

与整数相同的最好方法是什么?

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

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

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

请注意,这不允许负面的权力。 我会把这个作为练习留给你 🙂

补充:哦,是的,几乎忘了 – 也添加溢出/下溢检查,或者你可能会在路上几个令人讨厌的惊喜。

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); 

在John Cook的博客链接中使用math,

  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; } 

以解决这个问题,如果你改变权力的types,代码将无法正常工作,呃…抛开任何人改变代码,他们不明白,然后使用它没有testing的观点…..
但为了解决这个问题,这个版本保护愚蠢的错误…(但不是从他们可能做的其他无数)注意:没有testing。

  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; } 

也尝试这个recursion等效(当然慢):

  public static long IntPower(long x, int power) { return (power == 0) ? x : ((power & 0x1) == 0 ? x : 1) * IntPower(x, power >> 1); } 

这是一篇博客文章 ,解释了将整数提升为整数的最快方法。 正如其中一个评论指出的,这些技巧中的一部分被embedded到芯片中。

洛茨,怎么样:

 public static long IntPow(long a, long b) { long result = 1; for (long i = 0; i < b; i++) result *= a; return result; } 

使用双重版本,检查溢出(超过最大整数或最大长),并投到int或长?

我最喜欢的解决scheme是经典的分而治之的recursion解决scheme。 实际上乘n次的速度更快,因为它减less了每次乘法次数的一半。

 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。

还有两个…

  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); } 

我做了一些快速的性能testing


  • 小我:32毫秒

  • Sunsetquest(快速):37毫秒

  • Vilx:46毫秒

  • 查尔斯布雷塔纳(又名库克):166毫秒

  • Sunsetquest(简单):469毫秒

  • 3dGrabber(Linq版本):868毫秒

(testing笔记:intel i7第二代,.net 4,发布版本,发布版本,1M个不同的版本,只有0-10的exp)

结论:mini-me的性能和简单性都是最好的

精度testing非常less

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

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

在这种情况下,由于基数和指数是整数,所以不存在舍入误差。 结果也将是整数。

快速简单的一行。

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

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