#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0

    How to string with numbers to decimal number


    hi guys. i am new to programming...in general new to computer science :)
    anyway...i have the task to write a program where a string with a number is given and i have to get the output in a complete decimal number...wow!

    for example given the string: s[]="156";

    Code:
    int dec(char *s)
    {
        int a=0, b, i;
        for(i=0;s[i]!='\0';i++)
        {
            a=s[i]*pow(10,(strlen(s)-1+i));
            b=b+a;
            i++;
        }
        return b;
    }
    wouldnt it be just: 1*10^(2)+5*10^(1)+6*10^(0)=156 ?

    see the thing is...i have tried it this way, but it doesnt work?

    so can anyone please help me out?
    i am pretty much desperate right now.

    thank you all very much.

    -Anna
  2. #2
  3. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,109
    Rep Power
    1802
    The ASCII value of a digit character is not the same as its arithmetic value. Subtract the ASCII value of '0' from the character code to get its arithmetic value.

    C Code:
    a =(s[i] - '0') * pow( 10, (strlen(s)-1+i) ) ;


    You are also erroneously incrementing the loop control variable i in loop body as well as the for statement.

    Beyond that there are a number of points and improvements that can be applied to your code:

    First of all, your conversion is from a decimal string to an integer (not a decimal), the internal representation of data in any digital electronic computer is binary. It is only represented as decimal if you choose to display it as decimal - in which case it is simply presented as a string which is what you started with.

    Second strlen() is at not only inefficient to start with (as described here), but in this case it is loop invariant, so even more inefficient to unnecessarily evaluate it in on every iteration of the loop.

    Another efficiency improvement can be obtained by exploiting the fact that the power of ten for each iteration is a number series where the next value can be calculated from the previous result more efficiently than calling pow() on each iteration - to apply this, it is simplest to start with the least significant digit so you do not need to calculate the start value.


    C Code:
    int dec_to_int( const char* s )
    {
        int a = 0 ;
        int p = 1 ;
        int i ;
     
        for( i = strlen(s) - 1 && i >= 0; i-- )
        {
            a += ( s[i] - '0' ) * p ; 
            p *= 10 ;
        }
     
        return a ;
    }


    Before you go much further in C development, I strongly recommend that you start using a symbolic debugger. It allows you to step your code line by line or stop execution at a breakpoint, and to observe the value of variables and content of memory at each step.
    Last edited by clifford; April 16th, 2013 at 03:00 PM.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0
    wow thank you very much. i got it now.
    thanks again!
  6. #4
  7. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,109
    Rep Power
    1802
    Originally Posted by AnnaCStarter
    wow thank you very much. i got it now.
    thanks again!
    You are welcome. There was a typo in the code I posted previously; I have edited it and fixed that now.

    In the meantime, I came up with a solution that avoids the use of strlen(), starts from the most significant digit, and uses fewer variables. It works by multiplying the accumulator by 10 on all but the last iteration rather than maintaining a power-of-ten variable:

    C Code:
    int dec_to_int( const char* s )
    {
        int a = 0 ;
        int i = 0 ;
     
        while( s[i] != 0 )
        {
            a += ( s[i] - '0' ) ;
            i++ ;
     
            if( s[i] != 0 )
            {
            	a *= 10 ;
            }
        }
     
        return a ;
    }


    This however rather cumbersomely tests for the nul terminator twice per iteration. In most cases the following would be faster:

    C Code:
    int dec_to_int( const char* s )
    {
        int a = 0 ;
        int i ;
     
        for( i = 0; s[i] != 0; i++ )
        {
            a += ( s[i] - '0' ) ;
            a *= 10 ;
        }
     
        a /= 10 ;
     
        return a ;
    }


    The latter may be slower on some low end devices used in embedded systems that do not have a hardware divide instruction.
    Last edited by clifford; April 16th, 2013 at 03:31 PM.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    You lost me on that last one as to why the need to divide.

    My usual approach (I'd been biting my tongue up until now) is:
    Code:
    int dec_to_int( const char* s )
    {
        int a = 0 ;  // important that we initialize this to zero
        int i ;  // using array indexing instead of char pointer for sake of OP
    
        for( i = 0; s[i] != 0; i++ )
        {
            a *= 10;   // decimal shift left; no effect first time since 10*0 is 0
            a += ( s[i] - '0' ) ;  // convert and add the digit
        }
        return a;
    }
    This could also be embedded in-line in code that's scanning an input stream, in which case it starts at the first digit character and stops at the next non-digit character.

    There's more than one way.

    PS
    Wait a minute. Back-slash-equal (\=)?

    Comments on this post

    • clifford agrees : I fixed the divide operator in my post (and tested the code since) - for what its worth since your solution is superior in any case.
    Last edited by dwise1_aol; April 16th, 2013 at 03:33 PM.
  10. #6
  11. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,109
    Rep Power
    1802
    Originally Posted by dwise1_aol
    You lost me on that last one as to why the need to divide.
    Because I (stupidly) applied the x10 on each iteration after the accumulation, not before as you did. You win! :)

    Not only that, but a decent optimising compiler will convert the operation into a single multiply-accumulate instruction where available, although it might do so more readily if written:

    Code:
    a = a * 10 + (s[i] - '0') ;
  12. #7
  13. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,109
    Rep Power
    1802
    Originally Posted by dwise1_aol
    I'd been biting my tongue up until now
    Getting there in one step would have been far less instructive to Anna perhaps. Avoidance of loop invariants and repeated evaluation of a series is usually a far more significant optimisation than the avoidance of an additional test or a single divide, and that point may have been missed otherwise.
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    OK, somehow I didn't see the a *= 10 ; inside the loop.

    Not trying to compete, but I did recall this from The Tao of Programming:
    Thus spake the master programmer:
    "When you have learned to snatch the error code from the time frame, it will be time for you to leave."
    (for the parody's context, refer to the 70's TV show, Kung Fu)
  16. #9
  17. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Originally Posted by clifford
    Getting there in one step would have been far less instructive to Anna perhaps. Avoidance of loop invariants and repeated evaluation of a series is usually a far more significant optimisation than the avoidance of an additional test or a single divide, and that point may have been missed otherwise.
    Indeed. A general approach that I normally advise is to first describe the manual process as a detailed procedure and then convert that manual process into code. For that reason, I didn't want to step in with what I felt was a simpler approach until she had indicated that she understood your method. But then that last version with the division at the end and my not spotting the multiplication inside the loop made me curious so I finally piped in.

    So now she has two methods, one of which she already understands and the other which should make sense after she's thought about it.

IMN logo majestic logo threadwatch logo seochat tools logo