 Why is pow() function giving wrong answer

19 Views

I'm trying to multiply 2, 3 digit numbers. I used 2 for loops (nested) and multiplied each digit of num1 with num2, and shifted each result to the appropriate place using pow(). So the problem is pow(10,3) is coming out to be 299 instead of 300.

I haven't tried much as but used printf to find what is actually happening in the runtime and this is what I have found. the values of tempR after shift should be
`5,40,300,100,800,6000,1500,12000,90000`
but are coming as
`5,40,299,100,799,6000,1500,12000,89999`

``````int main(void)
{
int result; // final result
int  tempR; // temporary for each iteration
char a[] = "345"; // number 1
char b[] = "321"; // number 2
for(int i = 2;i>= 0 ; i --)
{
for(int j = 2;j >= 0 ; j --)
{
int shift = abs(i-2 + j -2);
printf("%d
",shift);  //used to see the values of shift.
//and it is coming as expected
tempR = (int)(b[i] - '0') * (int)(a[j] - '0');
printf("%d
",tempR);    // value to tempR is perfect
tempR = tempR*pow(10,shift);
printf("%d
",tempR);  // here the problem starts
result += tempR;
}
}

printf("%d",result);
}`````` The `pow` function operates on doubles. Doubles use finite precision. Conversion back to integer chops rather than rounding.

Finite precision is like representing 1/3 as `0.333333`. If you do `9 * 1/3` and chop to an integer, you'll get 2 instead of 3 because `9 * 1/3` will give `2.999997` which chops to two.

This same kind of rounding and chopping is causing you to be off by one. You could also round by adding 0.5 before chopping to an integer, but I wouldn't suggest it.

Don't pass integers through doubles and back if you expect exact answers.

Although IEEE754 (ubiquitous on desktop systems) is required to return the best possible floating point value for certain operators such as addition, multiplication, division, and subtraction, and certain functions such as `sqrt`, this does not apply to `pow`.

`pow(x, y)` can and often is implemented as `exp(y * ln (x))`. Hopefully you can see that this can cause the `pow`result to "go off" spectacularly when used with seemingly trivial integral arguments. In your case, the rot truly sets in when you truncate the result to an `int`.

The moral of the story is to borrow an implementation of `pow` that takes integral arguments from a respected mathematics library (they use a technique called exponention by squaring), or roll your own. Using `round`is also a technique, if a little kludgy if you get my meaning. 