4

pow() function is giving very strange outputs.

I tried various combinations :

#include<stdio.h>
#include<math.h>
int main()
{
  int d=1;
  long long n1,n2;
  while(d<10)
  {

     n1=pow(10,d);
     n2=pow(10,d);
     d++;
     printf("%lld %lld\n",n1,n2);
  }
 }

this gives the wrong output i.e. 99 instead of 100 and like that.

now if i remove one of the variables, ans. is correct. if instead of d, i use a constant, ans is correct. if i take n1 and n2 as double, ans is correct.

So having two pow() functions with both having variables as the power and type casted as integers is giving bad output. Why this strange behaviour??

Aman Gupta
  • 191
  • 2
  • 3
  • 10

2 Answers2

5

This is a case of making an integer from a floating point value (which truncates the decimals, not rounding it), along with the fact that pow(x, y) translates to exp(log(x) * y), which will produce a result that isn't PRECISELY the same as xy - just a near approximation as a floating point value, such as 99.9999996 (or 100.00002) for 102.

If you want to round it, use round(pow(x, y)).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • But then it should be a consistent problem.. isnt it?? If i use only one pow() in the code then the answer is coming out to be correct even though i am converting it into integer. how is one pow() affecting the other?? – Aman Gupta Jun 15 '13 at 10:26
  • 1
    Compilers do all manner of optimisations. If you have only one call to `pow`, it may well decide that it can optimise that by simply multiplying by 10 each time. In the case when you have two calls to `pow`, it decides to actually call `pow`, because it takes up too much code-space to do the calculation, or something like that. – Mats Petersson Jun 15 '13 at 10:29
  • Thank you Mats!! I was completely unaware of any such optimisations done by compiler. – Aman Gupta Jun 15 '13 at 10:33
  • `pow(x, y)` does not “translate to” `exp(log(x) * y)` any more than `x*y` translates to `exp(log(x) + log(y))`. – Eric Postpischil Jun 16 '13 at 02:40
  • @EricPostpischil: No, it's a much more complicated calculation. And on i386 it differentiates between integer values for `y` and does a loop. But in the case of `y` being non-integer, it does `2^fract(y*log2(x))*2^int(y*log2(x))` - which isn't EXACTLY what I wrote, but close enough in my book. I'm pretty sure that that standard says nothing about how this should be implemented. But if the OP's function do to `pow` actually does a loop of integer steps [it also optimises and does `x*x` if the current `y` value is even, but that shouldn't change things], how come it comes up with a 99 value? – Mats Petersson Jun 16 '13 at 08:14
  • @MatsPetersson: It appears contradictory to write both “it does `2^fract(y*log2(x))*2^int(y*log2(x))`” and “[the] standard says nothing about how this should be implemented.” Only the latter is correct. The computation of `pow` is more complicated than I can write about in a comment. The question assuming `pow` uses a loop of integer steps is a non sequitur; I did not raise that as a possibility. – Eric Postpischil Jun 16 '13 at 16:01
  • The formula is from `glibc` - and supports my statement that it's a form of `exp(log(x) * y)` type computation. Of course, each C library has the right to implement this in any way they like (that produces a sufficiently accurate result). Without writing a complete essay on the possible ways to calculate `pow()`, how would you explain what it does - it's clearly not possible to simply implement as a loop [although, again, glibc detects "integer y" and does performs the necessary caclulation using a loop]. Maybe I should have just said "the calculation, which is magical, uses floating point". – Mats Petersson Jun 16 '13 at 17:56
2

When you use pow with variables, its result is double. Assigning to an int truncates it, and you get 99 instead of 99.9999999.

Using pow without variables is optimized by compiler (this is computed in compile-time).

nullptr
  • 11,008
  • 1
  • 23
  • 18
  • but one of the pow() is giving correct ans. even with variables. only in case of two pow() functions in the code, second pow() is giving wrong ans – Aman Gupta Jun 15 '13 at 10:29