I am calculating the n'th root of a positive integer using standard library method pow() .Here is the snippet from my program :
double x,y;
x=pow(64,(1.0/3));
int z;
printf("x=%lf\n",x);
z=(int)x;
printf("%d\n",z);
But while finding cube root of 64. X is printed as 4.000000 while z as 3. Why so ?
Can someone suggest a better algorithm , for the same ?
If you print more digits on x
, you'll see what the problem is (I chose 30 randomly):
double x ;
x = pow(64, 1.0/3);
printf("x=%.30lf\n",x);
Output:
x=3.99999999...999600000000
So obvisouly, if you cast x
into a int
it will became 3
.
There is not a 'perfect' solution. If you're only dealing with integer, you could create your own root function, but if you want to be able to use float, you'need to deal with accuracy problem due to floating point representation.
There are maybe some C libraries which could help you with this kind of problems.
The int
override rounds down. Since floating point operations are inaccurate, the calculation may be 3.999999...
Use round(x)
to get the correct result.
Since you always want to round down, you can use both floor
and (int)
-- but you run into the observed error as soon as the instability of floating point calculations results in a slightly less value -- something in the order of 10-15, for double
sized calculations. Use a tiny epsilon value to counteract that.
Note that the epsilon "fudge" value below will relate to the number of significant digits in your original number. For larger numbers, you need a smaller epsilon.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main (void)
{
double x;
int z;
x=pow(64,(1.0/3));
printf("x=%lf\n",x);
printf("x=%.30lf\n",x);
z=(int)x;
printf("%d\n",z);
z=(int)(x+0.000000000000005);
printf("%d\n",z);
x=pow(64,(1.0/4));
printf("x=%lf\n",x);
printf("x=%.30lf\n",x);
z=(int)x;
printf("%d\n",z);
z=(int)(x+0.0000000000000005);
printf("%d\n",z);
return 1;
}
results, for powers of 1/3 and 1/4, in
x=4.000000
x=3.999999999999999555910790149937
3
4
x=2.828427
x=2.828427124746190290949243717478
2
2
As told by @jongware The int override rounds down and floating point operations may be inaccurate .
though you can always do this to evade this problem
def invpow ( n , i):
x = pow (n ,(1/i))
if((int)pow((x+1) , i) <= n):
x += 1;
print(x)
Or you can write your own method for exponentiation by using Newton - Raphson method described here and here
you can also use Binary search which is quite fast if you have right guess for the range ie (variables high and low )
def invpow( x, n, low, high){
if(n==1)
return x;
mid=(low+high)/2;
while(low<high){
mid=(low+high)/2;
raised=pw(mid,n);
if(raised==x)
break;
if(raised>x)
high=mid;
else
low=mid;
if(low+1==high){
mid=low;
break;
}
}
return mid;
}
来源:https://stackoverflow.com/questions/24105367/wrong-answer-while-calculating-the-nth-root-of-number-in-cpp