c功率计算,编译器优化

时间:2013-10-20 13:08:34

标签: c optimization numerical stability

所以我最近一直在处理订单统计的一些概率分布。在那个区域,从实际区间[0,1]中看到许多具有高幂数的公式是很常见的。

考虑数字a~b~0,均为正数。我想计算像^ n / b ^ m这样的东西 其中n,m是巨大的数字。

我的问题如下: 如果我使用像

这样的C代码
double f(double a, double b, long m, long n)
{
    return( pow(a, n) / pow(b, m) );
}
这会稳定吗?规则应该首先评估a ^ n,然后b ^ m然后除以,如果 a ^ n或b ^ m足够小,它只是零或NaN。相反,我可以做类似

的事情
double g(double a, double b, long m, long n)
{
    double res;
    long i;
    res = 1;
    for (i = 0; i < min(m, n); ++i)
    {
        res = res * a / b;
    }
    if ( n > m )
    {
        res = res * pow(a, n - m);
    } else {
       res = res / pow(b, m - n);
    }
    return( res );
}

您是否知道1)在这种情况下是否会受到优化?如果没有,那么如何处理这种情况以进行快速稳定的评估呢?

1 个答案:

答案 0 :(得分:3)

如果你问pow()是否通过重复乘法实现取幂,答案是否定的。您可以假设它已经过优化,因此通过检查零分子可能实现的任何节省可能是微不足道的。你肯定不希望用for()循环来实现它,它循环遍历大量的浮点计算。

另一方面,最好避免除以零。

我会像这样实现你的功能:

double f(double a, double b, long m, long n) {
  if (b == 0) {
    // return error or infinity.
  }
  if (m >= n)
    return pow(a / b, n) * pow(a, m - n);
  else 
    return pow(a / b, m) / pow(b, n - m);
  }
}