2

I have an exercise which demands a program that reverts a five digit number using pow, here is my try:

#include <math.h>
#include <stdio.h>
void main( void )
{
    int number, counter = 0, last_digit, reversed = 0;

    printf( "Please type a five digit number and I will reverse it\n" );
    scanf( "%d", &number );

    for( counter = 4; counter >= 0; counter-- )
    {
        last_digit = number % 10;
        number = number / 10;

        //printf( "%d %d %.0f %.0f\n\n", reversed, last_digit, pow ( 10, counter ), reversed + last_digit * pow( 10, counter ));

        reversed = reversed + last_digit * pow( 10, counter );
    }//end for

    printf( "The number reversed is %d", reversed );
}//end main

But if I type 12345 it returns 54320, the last digit is wrong! To check what was going on I enabled the printf comment an here it is a sample of execution:

Please type a five digit number and I will reverse it
12345 

0 5 10000 50000 
49999 4 1000 53999 
53999 3 100 54299 
54299 2 10 54319 
54319 1 1 54320 

The number reversed is 54320

For some reason the first 50000 is converted to 49999, there is one less! And the weird part is that it only happens the first time, then for example 53999 is correctly converted to 53999. What is happening here?

user3646717
  • 1,095
  • 2
  • 12
  • 21
  • 2
    pow returns a floating point number. don't expect it to be precise. one solution is to do (int)(pow(10, counter) + 0.5). another solution is to implement your own myPow function using e.g. a for loop and integer arithmetic. – d0c Sep 06 '14 at 00:38
  • 2
    Off by 1 on floating point normally indicates a rounding error. Make `reversed` a `double` during the calculation. – leppie Sep 06 '14 at 00:38
  • 1
    Use `reversed = reversed + last_digit * round(pow(10, counter));` – chux - Reinstate Monica Sep 06 '14 at 02:41
  • 2
    check out this link: http://stackoverflow.com/questions/9704195/why-pow10-5-9-999-in-c – shoham Sep 06 '14 at 04:13

2 Answers2

1

You can use round(pow(10,counter))

radar
  • 13,270
  • 2
  • 25
  • 33
1

As the other commenters said, the issue is with rounding. pow() returns a double, and pow(10,4) must be returning a double close to 10000 but a bit or two off. Then in your print statement, when you print reversed + last_digit * pow( 10, counter ), this value is a double, close to 50000, but a bit off. When it prints, printf rounds to the precision you print to, so it prints as 50000. But when you assign to the integer reversed, the value is truncated, and if it is even one bit below 50000, it becomes 49999. Your teacher devised a very nice question - teaches nicely!

David I. McIntosh
  • 2,038
  • 4
  • 23
  • 45
  • Then why does it do it only the first time? – user3646717 Sep 06 '14 at 01:08
  • Because of the details of the computation in the pow() function. For the other particular values (pow(10,3), pow(10,2) etc.) the value that the pow() function returns is likely exactly the integer (1000, 100, etc.) or a bit over, so that truncating gives you the exact integer you are looking for. – David I. McIntosh Sep 06 '14 at 01:43
  • When you are programmin in strict C and you call the pow() function, it doesn't matter that the second parameter is an integer, it converts it to a double and calls the same pow(double,double) function. And this function calculates pow(x,y) by _essentially_ calculating exp( y* ln(x) ). As you can imagine, numerical errors creep in. In a language like C++, pow() can have multiple versions (overloads) so that when the y parameter is an integer, it calls a version pow(double,int), and this version can calculate pow() by doing simple multiplication (and possibly inversion 1/x if y is negative). – David I. McIntosh Sep 06 '14 at 01:50
  • The next exercise you should do is to implement a `double pow(double x, int n)` function that calculates the value by doing only multiplications and (possibly) one inversion (division). If n is a 32-bit signed integer, this can be done with at most 60 multiplications and one division (and, a big hint, 30 right-shifts). – David I. McIntosh Sep 06 '14 at 02:03