Forums: » Register « |  Free Tools |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support |

New Free Tools on Dev Shed!

#1
April 15th, 2013, 03:57 PM
 AnnaCStarter
Registered User

Join Date: Apr 2013
Posts: 7
Time spent in forums: 1 h 15 m 9 sec
Reputation 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?

i am pretty much desperate right now.

thank you all very much.

-Anna

#2
April 15th, 2013, 05:34 PM
 clifford
Contributing User

Join Date: Aug 2003
Location: UK
Posts: 4,967
Time spent in forums: 1 Month 4 Days 3 h 49 m 40 sec
Reputation Power: 1801
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:
 Original - 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:
 Original - 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 04:00 PM.

#3
April 16th, 2013, 12:21 PM
 AnnaCStarter
Registered User

Join Date: Apr 2013
Posts: 7
Time spent in forums: 1 h 15 m 9 sec
Reputation Power: 0
wow thank you very much. i got it now.
thanks again!

#4
April 16th, 2013, 04:18 PM
 clifford
Contributing User

Join Date: Aug 2003
Location: UK
Posts: 4,967
Time spent in forums: 1 Month 4 Days 3 h 49 m 40 sec
Reputation Power: 1801
Quote:
 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:
 Original - 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:
 Original - 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 04:31 PM.

#5
April 16th, 2013, 04:30 PM
 dwise1_aol
Contributing User

Join Date: Jan 2003
Location: USA
Posts: 6,868
Time spent in forums: 3 Months 1 Day 7 h 53 m 33 sec
Reputation Power: 2199
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 (\=)?
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 04:33 PM.

#6
April 16th, 2013, 04:44 PM
 clifford
Contributing User

Join Date: Aug 2003
Location: UK
Posts: 4,967
Time spent in forums: 1 Month 4 Days 3 h 49 m 40 sec
Reputation Power: 1801
Quote:
 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') ;`

#7
April 16th, 2013, 04:53 PM
 clifford
Contributing User

Join Date: Aug 2003
Location: UK
Posts: 4,967
Time spent in forums: 1 Month 4 Days 3 h 49 m 40 sec
Reputation Power: 1801
Quote:
 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.

#8
April 16th, 2013, 04:57 PM
 dwise1_aol
Contributing User

Join Date: Jan 2003
Location: USA
Posts: 6,868
Time spent in forums: 3 Months 1 Day 7 h 53 m 33 sec
Reputation Power: 2199
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:
Quote:
 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)

#9
April 16th, 2013, 05:05 PM
 dwise1_aol
Contributing User

Join Date: Jan 2003
Location: USA
Posts: 6,868
Time spent in forums: 3 Months 1 Day 7 h 53 m 33 sec
Reputation Power: 2199
Quote:
 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.

 Viewing: Dev Shed Forums > Programming Languages > C Programming > How to string with numbers to decimal number