我在哪里弄错了? 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)相同。
答案 0 :(得分:2)
因此,重复将浮点数除以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);
}
答案 1 :(得分:0)
结束递归的唯一条件是n为零。只有连续除以2得到零结果(这基本上意味着浮动类型的下溢)才能实现。这需要一段时间才能获得大值。