为啥 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 的整数值。现在会更新。 @hobbsfmod
的复杂度是多少?
这里使用大 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 需要更长的时间?