c# – Math.Pow的最佳实践

前端之家收集整理的这篇文章主要介绍了c# – Math.Pow的最佳实践前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在开发一个扩展OpenCV,HALCON,……的图像处理库.该库必须与.NET Framework 3.5一起使用,由于我对.NET的经验有限,我想问一些有关性能的问题.

我遇到了一些我无法正确解释的具体事情,并希望你问a)为什么和b)处理案件的最佳做法是什么.

我的第一个问题是关于Math.pow.我已经在StackOverflow上找到了一些答案,这很好地解释了它(a)但不知道如何处理(b).我的基准程序看起来像这样

  1. Stopwatch watch = new Stopwatch(); // from the Diagnostics class
  2. watch.Start();
  3. for (int i = 0; i < 1000000; i++)
  4. double result = Math.Pow(4,7) // the function call
  5. watch.Stop()

结果不是很好(在我的电脑上约300毫秒)(我已经运行了10次测试并计算了平均值).

我的第一个想法是检查这是因为它是一个静态功能.所以我实现了自己的课程

  1. class MyMath
  2. {
  3. public static double Pow (double x,double y) //Using some expensive functions to calculate the power
  4. {
  5. return Math.Exp(Math.Log(x) * y);
  6. }
  7.  
  8. public static double PowLoop (double x,int y) // Using Loop
  9. {
  10. double res = x;
  11. for(int i = 1; i < y; i++)
  12. res *= x;
  13. return res;
  14. }
  15.  
  16. public static double Pow7 (double x) // Using inline calls
  17. {
  18. return x * x * x * x * x * x * x;
  19. }
  20. }

我检查的第三件事是我是否会直接通过4 * 4 * 4 * 4 * 4 * 4 * 4替换Math.Pow(4,7).

结果是(10次试运行中的平均值)

  1. 300 ms Math.Pow(4,7)
  2. 356 ms MyMath.Pow(4,7) //gives wrong rounded results
  3. 264 ms MyMath.PowLoop(4,7)
  4. 92 ms MyMath.Pow7(4)
  5. 16 ms 4*4*4*4*4*4*4

现在我现在的情况基本上是这样的:不要使用Math for Pow.我唯一的问题就是……我真的必须现在实现自己的数学课吗?为电源功能实现一个自己的类似乎有点无效. (顺便说一下,PowLoop和Pow7在Release版本中的速度甚至更快了~25%,而Math.Pow却没有).

所以我最后的问题是

a)如果我根本不使用Math.Pow(但对于分数可能)(这让我感到难过),我错了.

b)如果你有优化的代码,你是否真的直接编写所有这些数学运算?

c)可能已经存在用于数学运算的更快(开源^^)库

d)我的问题的根源基本上是:我假设.NET Framework本身已经为这样的基本操作提供了非常优化的代码/编译结果 – 无论是Math-Class还是处理数组,我有点惊讶有多少好处我会通过编写自己的代码来获益.在C#中是否还有一些其他的,一般的“字段”或其他内容,我不能直接信任C#.

解决方法

要记住两件事:

>你可能是don’t need to optimise这段代码.你在不到一秒的时间内完成了对该功能的一百万次调用.这真的会给你的程序带来很大的问题吗?
>无论如何,Math.Pow可能是相当优化的.在猜测中,它将调用一个用较低级语言编写的适当的数字库,这意味着你不应该期望数量增加.
>数值编程比你想象的更难.即使您认为自己知道如何计算的算法,也不会以这种方式计算.例如,当您计算平均值时,您不应该只是将数字相加并除以您拥有的数字. (现代数字库使用两遍例程来纠正浮点错误.)

也就是说,如果您确定您确实需要优化,那么请考虑使用整数而不是浮点值,或将其外包给另一个数字库.

猜你在找的C#相关文章