为啥 c 中的幂函数需要比预期更长的时间

Posted

技术标签:

【中文标题】为啥 c 中的幂函数需要比预期更长的时间【英文标题】:Why does power function in c take longer than expected for large numbers为什么 c 中的幂函数需要比预期更长的时间 【发布时间】:2015-02-08 05:45:53 【问题描述】:

我哪里弄错了? c/c++ 中的 pow(double,double) 函数在 O(log n) 时间内运行,这意味着计算长数字的幂不需要明显的时间。我编写了一个函数来以对数时间计算 a^b mod m,这又比预期的要长。 函数定义为:

float pow(float a,float n,float m)
  float temp,temp2;
  if(n==0)
    return 1;
  temp=pow(a,n/2,m);
  if(fmod(n,2)==0)
    if(temp>m)
      temp=fmod(temp,m);
    
    temp2=temp*temp;
    if(temp2>m)
      temp2=fmod(temp2,m);
    return temp2;
  
  else
    if(temp>m)
      temp=fmod(temp,m);
    
    temp2=temp*temp*a;
    if(temp2>m)
      temp2=fmod(temp2,m);
    return temp2;
  

如果我调用 pow(10^9,10^9,123) 我希望它以 ~ O(log(10^9)) 复杂度运行,因此在我的计算机上完成不到 1 秒(O(10^8)运行 1 秒)。但它就像永远一样。 std::pow(double,double) 也是如此。

【问题讨论】:

你递归直到一个浮点数,反复除以 2,变成 0?真的吗? 对此我很抱歉。但这不是问题。我只传递 n 的整数值。现在会更新。 @hobbs fmod 的复杂度是多少? 这里使用大 O 表示法不太正确。 O(10^8) 和 O(1) 是一样的。 将函数命名为与标准函数相同是不好的 【参考方案1】:

因此,重复将浮点数除以 2 只会在您用完指数时完成。 (为了好玩,请尝试传入1.0f/0.0f。)

int func(float n) 
    if (n == 0)
        return 1;
    return 1 + func(n / 2);

在我的系统上,func(1.0f) 给出 151。这可能不是你想要的!

你想要这个:

float pow(float a, int n, float m) 
    if (n == 0)
        return 1.0f;
    float t = pow(a, n / 2, m);
    return fmodf((n & 1) ? t*t*a : t*t, m);

请注意,pow() 完全不同。 pow() 的定义更接近于:

float powf(float x, float y) 
    if (...) 
        // faster, special case versions
    
    return expf(logf(x) * y);

【讨论】:

感谢您的回答。但是当我用大于 10^9 的值调用数学库的 pow 函数时,问题仍然存在。 @jmathews:你能告诉我们这是怎么发生的吗?在我的系统上,pow() 非常快。你用的是什么数学库? (或者你使用的是什么编译器/操作系统) 你能试试 pow(123123123,123123123)。当然会溢出但是返回值快吗? 我得到:0.00s user 0.00s system 0% cpu 0.003 total 计算所需的时间。这是关闭优化,pow 的参数取自 argv @jmathews:我在没有优化的情况下循环运行了 10^8 次,每次调用 pow() 记录的平均时间约为 62 纳秒。【参考方案2】:

结束递归的唯一条件是 n 是否为零。只有连续除以 2 得到零结果(这基本上意味着浮点类型下溢)时,才能实现这一点。对于较大的值,这需要一段时间。

【讨论】:

以上是关于为啥 c 中的幂函数需要比预期更长的时间的主要内容,如果未能解决你的问题,请参考以下文章

为啥通过 ASP.NET 方法运行查询比原生 SQL 需要更长的时间?

为啥一个循环比另一个循环检测共享内存更新需要更长的时间?

为啥我使用 modin.pandas 比使用 Pandas 需要更长的时间 [ray]

为啥检查错误的密码比检查正确的密码要花更长的时间?

NHibernate 执行简单查询需要更长的时间

java - 多线程中的简单计算比单线程中需要更长的时间