【问题标题】:Why isn't there Math.Pow that takes an int as the exponent?为什么没有以 int 作为指数的 Math.Pow?
【发布时间】:2011-10-18 15:26:49
【问题描述】:

我读到Math.Pow 的实现非常复杂,无法处理分数幂。当您不需要分数幂时,为什么没有一个版本需要一个 int 的指数来生成更快的版本?

【问题讨论】:

  • 在 SO 上查看此链接:stackoverflow.com/questions/383587/…
  • 谢谢,但它会像 MS 版本那样快吗?因为他们对 Pow 方法使用外部调用。
  • 外部调用不能直接保证速度。
  • 感谢 Henk,我以为他们想用 C++ 编写它以使其更快。对于这种情况,还有什么其他理由这样做?
  • 我在这里和一位图形程序员交谈,他说处理小数幂的实现比仅仅乘以值要复杂得多,所以我假设即使我的指数是相同的性能损失不是分数。

标签: c# .net performance math


【解决方案1】:

因为您只需要将其转换回浮点数,然后将其与底数的对数相乘。

nm = em × ln n

【讨论】:

  • @BlueRaja OP 明确声明仅 int 表示指数。
  • 除非您使用整数算术实现整数幂运算...这可能比运行那些 exp 和 ln 更快。
【解决方案2】:

我不认为快速数学函数是他们编程时的首要任务(请参阅Why is Math.DivRem so inefficient)。 他们可以使用更快的平方取幂,至少对于小指数而言。

但是,由于浮点数需要四舍五入,因此提供 2 个不同的实现可能意味着不同的结果,例如对于 pow(5.9,7) 而不是对于 pow(5.9,7.0),这在某些情况下可能是不可取的。

【讨论】:

  • “pow”函数可以保证什么级别的准确度?在提高到整数幂时保证 0.5625ulp 内的精度有点棘手,但在使用 exp(ln(base)*pow) 时保证精度就更难了。 C 语言的扩展精度支持过于拙劣,以至于此类类型通常不可用,因为它们更容易产生精确到 double 精度的结果。
【解决方案3】:

嗯,你可以自己写(用 C 语言):

int intPow(int a,int b){
  int answer = a;
  int i;
  for(i=0;i<b-1;i++)
    answer *= a;
  return answer;
}

【讨论】:

  • 只有更聪明(更快)的方法可以做到这一点。
  • 请注意,这在 O(N) 中运行。一个好的 pow 实现可以在 O(logN) 中运行
  • 这是非常低效的。而且它不编译。我认为 OP 认为 a 是一个浮点值。
  • @David Heffernan - 只是好奇,您能否提供一个比 O(logN) 更好的 pow 算法示例(如果解释太长,请提供链接)?快速浏览一下 Wikipedia 似乎没有比这更好的建议了……
  • Knuth 第 2 卷,第 4.6.3 节对权力评估进行了详尽的阐述
【解决方案4】:

对于编译器,如果指数是常数,则只有通过转换为一系列乘法来进行优化才值得。在这种情况下,您可以自己写x*xx*x*x

编辑:因此,如果您想避免通过 Math.Pow 实现(使用指数函数)完成数学运算,请不要调用它。如果为整数添加 Math.Pow,编译器会从如何调用它来确定它是否应该发出乘法代码(如果 n 是常量且很小)或使用指数函数的默认值。对于编译器来说,这不是微不足道的工作,而且在性能方面不会有任何收获。

【讨论】:

  • 所以你认为如果我做 Math.Pow (3, 5) 会优化吗?调用是外部的,所以我看不到代码。
  • 这完全没有抓住重点。 Math.Pow 不进行一系列乘法运算。即使它这样做了,它背后的库代码也会使用中间值,即使在编译时不知道指数。
猜你喜欢
  • 2016-04-10
  • 2016-02-14
  • 1970-01-01
  • 2017-05-22
  • 2013-02-17
  • 2017-05-31
  • 2014-05-22
  • 1970-01-01
相关资源
最近更新 更多