C: I have different results with pow (10,2) and pow (10, j), j = 2;

this one prints 100:

int j=2; int i= pow(10,2); printf("%d\n", i); 

and he prints 99:

 int j=2; int i= pow(10,j); printf("%d\n", i); 

why?

+8
c floating-point pow
01 Oct '13 at
source share
3 answers

What happens is that you have a C implementation whose standard library has a very low quality pow implementation that returns inaccurate results, even if the exact result is presented in a ( double ) type. The pow(10,2) call seems to create a value just below 100.0 , which when rounded to an integer gives 99. The reason you don't see this when the arguments are constant is because the compiler allowed us to optimize the call to alltogether and replace it with constant 100 in compiletime.

If you intend to perform full authority, do not use the pow function. Write the correct integer power function, or when the exponent is known, just write the multiplication directly.

+12
01 Oct '13 at 23:08
source share
β€” -

In the first case, I suspect that the compiler optimized the value 10*10 without actually calling pow (compilers really do this). In the second case, it looks like you have a floating point rounding error. The result is almost 100, but not quite, and an implicit cast to int truncates it.

The pow function works on double , not int .

In the general case (but not always), when you convert double numbers to integers, you call round() . For example:

 int i = (int) round(pow(10,j)); 

If your C library does not have this, you can emulate:

 #define round(x) floor((x)+0.5) 
+2
01 Oct '13 at 22:19
source share

pow returns double , and therefore, if the result is not exactly 100 , but slightly less than what it will be truncated when converting to int , and you will get the result 99 that you see. It would be interesting to see what the results for the double and %f variables look like.

The reason you won't see it when using literals is due to the constant crease that will cause pow calls to be optimized and replaced by a constant. We can see the version that uses constants when generating the assembly, does not call pow , it simply moves the final result of 100 (see live ):

 movl $100, -4(%rbp) 

while the second version actually calls pow (see live ):

 call pow 
0
01 Oct '13 at 22:24
source share



All Articles