Binary to decimal
Author Message
Binary to decimal

Hi, while I was writing a simple program to
print the decimal number of a binary base two number
I realized that I still have to learn a bit about C:

(include here stdio, stdlib, string, and math too)

this is the main to test the problem:
int n_len;
int i, ii;
char *buffer;

double decimal = 0;

if (!argv[1])
printf("No number given\n");

n_len = strlen(argv[1]);

buffer = malloc(n_len + 1);
strcpy(buffer, argv[1]);

printf("%s =", buffer);

ii = n_len - 1;

for (i = 0; i < n_len; i++)
{

if (ii == 0)
printf(" %c x 2^%d\n", buffer[i], ii); /* no + */
else
printf(" %c x 2^%d +", buffer[i], ii);

/* the following for testing purpose */

buffer[i] = 1;  /* ! ATTENTION PLEASE ! */

decimal =  (int) buffer[i]  * (int) pow(2, ii);
printf("pow = %d\n", (int) decimal);

ii--;
}

runtime:
Let's assume argv[i] is: 11001
program output (with the attention please comment)
11001 = 1 x 2^4 +pow = 784
1 x 2^3 +pow = 392
0 x 2^2 +pow = 192
0 x 2^1 +pow = 96
1 x 2^0
pow = 49
binary: 11001

program output (withOUT the attention please comment)
11001 = 1 x 2^4 +pow = 16
1 x 2^3 +pow = 8
0 x 2^2 +pow = 4
0 x 2^1 +pow = 2
1 x 2^0
pow = 1
binary: 11001

DOh!!!!

I tought something like (int) buffer[i] * 2 was OK to do

--
Linux: Where Don't We Want To Go Today?
-- Submitted by Pancrazio De Mauro, paraphrasing some well-known sales talk

Tue, 21 Sep 2004 08:27:24 GMT
Binary to decimal
On Fri, 05 Apr 2002 02:27:24 +0200,

Quote:
> Hi, while I was writing a simple program to
> print the decimal number of a binary base two number
> I realized that I still have to learn a bit about C:

> (include here stdio, stdlib, string, and math too)

> this is the main to test the problem:
> int n_len;
> int i, ii;
> char *buffer;

>    double decimal = 0;

Why a double? You seem to want to interpret the "bit" pattern as an
unsigned int, so why don't you use a variable of that type? That is,
unless I totally misunderstood what you're trying to do.

Quote:
>    if (!argv[1])
>      printf("No number given\n");

You should probably check instead that argc >= 2, and exit if that's
not the case.

Quote:
>    n_len = strlen(argv[1]);

Maybe you should have some checks here to make sure the bit pattern
isn't too long, and only contains 1s and 0s. But that's not really
needed for this illustration.

Quote:
>    buffer = malloc(n_len + 1);
>    strcpy(buffer, argv[1]);

You don't need this buffer. You can work with argv[1] directly. All
you _need_ to do is read it.

Quote:
>    printf("%s =", buffer);

>    ii = n_len - 1;

>  for (i = 0; i < n_len; i++)
>     {

>       if (ii == 0)
>         printf(" %c x 2^%d\n", buffer[i], ii); /* no + */
>       else
>         printf(" %c x 2^%d +", buffer[i], ii);

>      /* the following for testing purpose */

>      buffer[i] = 1;  /* ! ATTENTION PLEASE ! */

>      decimal =  (int) buffer[i]  * (int) pow(2, ii);

I think you're missing the point that '1' (the character) is not the
same as 1. To translate '1' into 1, you can subtract '0', due to the
special property that the 10 digit characters will always have

Quote:
>      printf("pow = %d\n", (int) decimal);

>       ii--;
>     }
> I tought something like (int) buffer[i] * 2 was OK to do

It is, but it just doesn't do what you think it does.

Your program, rewritten a bit, to get rid of some unnecessary stuff,
and doing what I think you want it to do:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int main (int argc, char *argv[])
{
int i, exp;
unsigned int decimal = 0;

if (argc < 2)
{
printf("No number given\n");
return EXIT_FAILURE;
}

for (exp = 0, i = strlen(argv[1]) - 1; i >= 0; i--, exp++)
{
decimal += (argv[1][i] - '0') * pow(2, exp);
printf("  %c x 2^%d + decimal = %u\n", argv[1][i], exp, decimal);
}
printf("End result: decimal = %u\n", decimal);

return EXIT_SUCCESS;

Quote:
}

Martien
--
|
Martien Verbruggen      | Little girls, like butterflies, need no
Trading Post Australia  | excuse - Lazarus Long
|

Tue, 21 Sep 2004 08:52:11 GMT
Binary to decimal
On Fri, 05 Apr 2002 00:52:11 GMT,

Quote:
> On Fri, 05 Apr 2002 02:27:24 +0200,

>> Hi, while I was writing a simple program to
>> print the decimal number of a binary base two number

[snip of discussion of how to do that bit by bit]

Of course, if you're only interested in the end result, and not in how
to do it yourself, you could simply use strtol()

unsigned int decimal;
decimal = strtol(argv[1], NULL, 2);

(you might need to watch out for overflow problems when sizeof(long
int) isn't larger than sizeof(unsigned int)).

Martien
--
|
Martien Verbruggen      | For heaven's sake, don't TRY to be cynical.
Trading Post Australia  | It's perfectly easy to be cynical.
|

Tue, 21 Sep 2004 09:03:01 GMT
Binary to decimal

Quote:
> Hi, while I was writing a simple program to
> print the decimal number of a binary base two number
> I realized that I still have to learn a bit about C:

> (include here stdio, stdlib, string, and math too)

> this is the main to test the problem:
> int n_len;
> int i, ii;
> char *buffer;

[...]

Quote:
> DOh!!!!

> I tought something like (int) buffer[i] * 2 was OK to do

#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <math.h>

unsigned long bin2dec(const char *s)
{
const size_t LENGTH=strlen(s);

size_t i;
unsigned long decimal;

for(decimal=i=0; i<LENGTH; i++)
{
if(s[i]=='1')
decimal+=pow(2, LENGTH-(i+1));
}

return decimal;

Quote:
}

int main(void)
{
char binary[]="1101101";

printf("%lu\n", bin2dec(binary));

return 0;

Quote:
}

--
Ioannis

* Ioannis Vranos
* Programming pages: http://www.noicys.cjb.net
* Alternative URL: http://run.to/noicys

Tue, 21 Sep 2004 10:19:20 GMT
Binary to decimal
Snippets...
bascnvrt.c
ltostr.c
HTH
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm

Tue, 21 Sep 2004 08:55:58 GMT
Binary to decimal

Quote:

> >> Hi, while I was writing a simple program to
> >> print the decimal number of a binary base two number

> [snip of discussion of how to do that bit by bit]

> Of course, if you're only interested in the end result, and not in how
> to do it yourself, you could simply use strtol()

Or try the following:

/* Routines to display values in various bases         */
/* with some useful helper routines.                   */
/* by C.B. Falconer, 19 Sept. 2001                     */
/* Released to public domain.  Attribution appreciated */

#include <stdio.h>
#include <string.h>
#include <limits.h>  /* ULONG_MAX etc. */

/* ======================= */
/* reverse string in place */
size_t revstring(char *stg)
{
char  *last, temp;
size_t lgh;

lgh = strlen(stg);
if (lgh > 1) {
last = stg + lgh;        /* points to '\0' */
while (last-- > stg) {
temp = *stg; *stg++ = *last; *last = temp;
}
}
return lgh;

Quote:
} /* revstring */

/* ============================================ */
/* Mask and convert digit to hex representation */
/* Output range is 0..9 and a..f only           */
int hexify(unsigned int value)
{
static char hexchars[] = "0123456789abcdef";

return (hexchars[value & 0xf]);

Quote:
} /* hexify */

/* ================================================== */
/* convert unsigned number to string in various bases */
/* 2 <= base <= 16, controlled by hexify()            */
/* Returns actual output string length                */
size_t basedisplay(unsigned long number, unsigned int base,
char *stg, size_t maxlgh)
{
char *s;

/* assert (stg[maxlgh]) is valid storage */
s = stg;
if (maxlgh && base)
do {
*s = hexify(number % base);
s++;
} while (--maxlgh && (number = number / base) );
*s = '\0';
revstring(stg);
return (s - stg);

Quote:
} /* basedisplay */

/* ================================================ */
/* convert signed number to string in various bases */
/* 2 <= base <= 16, controlled by hexify()          */
/* Returns actual output string length              */
size_t signbasedisplay(long number, unsigned int base,
char * stg, size_t maxlgh)
{
char         *s;
size_t        lgh;
unsigned long n;

s = stg; lgh = 0;
n = (unsigned long)number;
if (maxlgh && (number < 0L)) {
*s++ = '-';
maxlgh--;
n = -(unsigned long)number;
lgh = 1;
}
lgh = lgh + basedisplay(n, base, s, maxlgh);
return lgh;

Quote:
} /* signbaseddisplay */

/* ==================== */
/* flush to end-of-line */
int flushln(FILE *f)
{
int ch;

while ('\n' != (ch = fgetc(f)) && (EOF != ch)) /* more */;
return ch;

Quote:
} /* flushln */

/* ========== END of generically useful routines ============ */

/* ========================= */
/* Prompt and await <return> */
static void nexttest(char *prompt)
{
static char empty[] = "";

if (NULL == prompt) prompt = empty;
printf("\nHit return for next test: %s", prompt);
fflush(stdout);
flushln(stdin);

Quote:
} /* nexttest */

/* ============================== */
/* Display a value and its length */
static void show(char *caption, int sz, char *stg)
{

if ((unsigned)sz != strlen(stg))
printf("Something is wrong with the sz value\n");
printf("%s: sz = %2d \"%s\"\n", caption, sz, stg);

Quote:
} /* show */

/* =========== */
/* exercise it */
int main(void)
{
#define LGH   40
#define VALUE 1234567890

char         stg[LGH];
unsigned int base;
int          sz;

printf("\nExercising basedisplay routine\n");
printf("\nbase sz value\n");
for (base = 2; base <= 16; base++) {
sz = (int)basedisplay(VALUE, base, stg, LGH - 1);
printf("%2d   %2d %s\n", base, sz, stg);
}

nexttest("ULONG_MAX");
for (base = 8; base <= 16; base++) {
sz = (int)basedisplay(ULONG_MAX, base, stg, LGH - 1);
printf("%2d   %2d %s\n", base, sz, stg);
}

basedisplay(0, 10, stg, 3);
printf("\nzero %s\n", stg);

basedisplay(VALUE, 10, stg, 3);
printf("3 lsdigits only, base 10 %s\n", stg);

sz = (int)basedisplay(VALUE, 10, stg, 0);
show("0 length field", sz, stg);

sz = (int)basedisplay(VALUE, 1, stg, 20);
show("base 1, lgh 20", sz, stg);

sz = (int)basedisplay(VALUE, 0, stg, 20);
show("base 0, lgh 20", sz, stg);

sz = (int)signbasedisplay(-1234, 10, stg, 0);
show("0 lgh fld, -ve", sz, stg);

sz = (int)signbasedisplay(-1234, 10, stg, 2);
show("truncate -1234", sz, stg);

nexttest("System limits");

sz = (int)signbasedisplay(SCHAR_MIN, 10, stg, 20);
show("SCHAR_MIN     ", sz, stg);

sz = (int)signbasedisplay(SCHAR_MAX, 10, stg, 20);
show("SCHAR_MAX     ", sz, stg);

sz = (int)signbasedisplay(UCHAR_MAX, 10, stg, 20);
show("UCHAR_MAX     ", sz, stg);

sz = (int)signbasedisplay(CHAR_MIN,  10, stg, 20);
show("CHAR_MIN      ", sz, stg);

sz = (int)signbasedisplay(CHAR_MAX,  10, stg, 20);
show("CHAR_MAX      ", sz, stg);

sz = (int)signbasedisplay(MB_LEN_MAX, 10, stg, 20);
show("MB_LEN_MAX    ", sz, stg);

sz = (int)signbasedisplay(SHRT_MIN,  10, stg, 20);
show("SHRT_MIN      ", sz, stg);

sz = (int)signbasedisplay(SHRT_MAX,  10, stg, 20);
show("SHRT_MAX      ", sz, stg);

sz = (int)signbasedisplay(USHRT_MAX, 10, stg, 20);
show("USHRT_MAX     ", sz, stg);

sz = (int)signbasedisplay(INT_MIN,   10, stg, 20);
show("INT_MIN       ", sz, stg);

sz = (int)signbasedisplay(INT_MAX,   10, stg, 20);
show("INT_MAX       ", sz, stg);

sz = (int)signbasedisplay(INT_MAX,   10, stg, 20);
show("INT_MAX       ", sz, stg);

sz = (int)    basedisplay(UINT_MAX,  10, stg, 20);
show("UINT_MAX      ", sz, stg);

sz = (int)signbasedisplay(LONG_MIN,  10, stg, 20);
show("LONG_MIN      ", sz, stg);

sz = (int)signbasedisplay(LONG_MAX,  10, stg, 20);
show("LONG_MAX      ", sz, stg);

sz = (int)    basedisplay(ULONG_MAX, 10, stg, 20);
show("ULONG_MAX     ", sz, stg);

nexttest("DONE");
return 0;

Quote:
} /* main */

--

Available for consulting/temporary embedded and systems.

Tue, 21 Sep 2004 10:28:59 GMT
Binary to decimal
Thanks a million for your help/suggestions/clarifications :)

--
Harrison's Postulate:
For every action, there is an equal and opposite criticism.

Tue, 21 Sep 2004 10:44:41 GMT
Binary to decimal

Quote:
> Hi, while I was writing a simple program to
> print the decimal number of a binary base two number
> I realized that I still have to learn a bit about C:
Yes you do.

<snip not very simple programme >
You are working too hard!
This is the way i would do it:
(error checking not shown.)

#include <stdio.h>
int main(int argc,char **argv){
long res=0;
if (argc==2){
char * bin=argv[1];
while(*bin)
res=res * 2 + *bin++ -'0';
printf("input string is %s  result is %ld\n",argv[1],res);
}
return 0;

Quote:
}

Roger...

Tue, 21 Sep 2004 10:56:46 GMT
Binary to decimal

Quote:

> This is the way i would do it:
> (error checking not shown.)

> #include <stdio.h>
> int main(int argc,char **argv){
> long res=0;
> if (argc==2){
>   char * bin=argv[1];
>   while(*bin)
>      res=res * 2 + *bin++ -'0';
>   printf("input string is %s  result is %ld\n",argv[1],res);
>   }
> return 0;
> }

It's clever but unfortunately it can't be considered portable on
non-ASCII systems.

--
Ioannis

* Ioannis Vranos
* Programming pages: http://www.noicys.cjb.net
* Alternative URL: http://run.to/noicys

Tue, 21 Sep 2004 21:19:45 GMT
Binary to decimal

Quote:

>> This is the way i would do it:
>> (error checking not shown.)

>> #include <stdio.h>
>> int main(int argc,char **argv){
>> long res=0;
>> if (argc==2){
>>   char * bin=argv[1];
>>   while(*bin)
>>      res=res * 2 + *bin++ -'0';
>>   printf("input string is %s  result is %ld\n",argv[1],res);
>>   }
>> return 0;
>> }
> It's clever but unfortunately it can't be considered portable on
> non-ASCII systems.

Yes it can. '1' - '0' is guaranteed to be 1 by ISO C.

--
Stefan Farfeleder

Tue, 21 Sep 2004 20:46:29 GMT
Binary to decimal

Quote:

> >> #include <stdio.h>
> >> int main(int argc,char **argv){
> >> long res=0;
> >> if (argc==2){
> >>   char * bin=argv[1];
> >>   while(*bin)
> >>      res=res * 2 + *bin++ -'0';
> >>   printf("input string is %s  result is %ld\n",argv[1],res);
> >>   }
> >> return 0;
> >> }

> > It's clever but unfortunately it can't be considered portable on
> > non-ASCII systems.

> Yes it can. '1' - '0' is guaranteed to be 1 by ISO C.

?

'some_number'-'0' is not portable since some encodings other than ASCII
have letter characters and number characters mixed.

--
Ioannis

* Ioannis Vranos
* Programming pages: http://www.noicys.cjb.net
* Alternative URL: http://run.to/noicys

Tue, 21 Sep 2004 22:26:29 GMT
Binary to decimal

Quote:

>> Yes it can. '1' - '0' is guaranteed to be 1 by ISO C.
> ?
> 'some_number'-'0' is not portable since some encodings other than ASCII

ITYM 'some_digit'

Quote:
> have letter characters and number characters mixed.

This part was quoted pretty often here in the last weeks, but here is it
once again:

[#3]  Both  the  basic  source and basic execution character
sets shall have at  least  the  following  members:  the  26
uppercase letters of the Latin alphabet

A  B  C  D  E  F  G  H  I  J  K  L  M
N  O  P  Q  R  S  T  U  V  W  X  Y  Z

the 26 lowercase letters of the Latin alphabet

a  b  c  d  e  f  g  h  i  j  k  l  m
n  o  p  q  r  s  t  u  v  w  x  y  z

the 10 decimal digits

0  1  2  3  4  5  6  7  8  9

the following 29 graphic characters

!  "  #  %  &  '  (  )  *  +  ,  -  .  /  :
;  <  =  >  ?  [  \  ]  ^  _  {  |  }  ~

the  space  character,  and  control characters representing
horizontal  tab,  vertical  tab,   and   form   feed.    The
representation  of  each  member of the source and execution
basic character sets shall fit  in  a  byte.   In  both  the
^^^^^^^^^^^^^
source and execution basic character sets, the value of each
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
character after 0 in the above list of decimal digits  shall
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
be  one  greater  than the value of the previous.  In source
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
files, there shall be some way of indicating the end of each
line  of  text;  this  International Standard treats such an
end-of-line indicator  as  if  it  were  a  single  new-line
character.   In  the execution character set, there shall be
control characters representing alert,  backspace,  carriage
return,   and   new  line.   If  any  other  characters  are
encountered in a source file (except  in  an  identifier,  a
character  constant,  a  string  literal,  a  header name, a
comment, or a preprocessing token that is never converted to
a token), the behavior is undefined.

--
Stefan Farfeleder

Tue, 21 Sep 2004 21:57:17 GMT
Binary to decimal

Quote:

>>>>#include <stdio.h>
>>>>int main(int argc,char **argv){
>>>>long res=0;
>>>>if (argc==2){
>>>>  char * bin=argv[1];
>>>>  while(*bin)
>>>>     res=res * 2 + *bin++ -'0';
>>>>  printf("input string is %s  result is %ld\n",argv[1],res);
>>>>  }
>>>>return 0;
>>>>}

>>>It's clever but unfortunately it can't be considered portable on
>>>non-ASCII systems.

>>Yes it can. '1' - '0' is guaranteed to be 1 by ISO C.

> ?

> 'some_number'-'0' is not portable since some encodings other than ASCII
> have letter characters and number characters mixed.

No. '0' through '9' are guaranteed to be in sequence.

--
Thomas

Tue, 21 Sep 2004 22:03:15 GMT
Binary to decimal

Quote:

> > >> #include <stdio.h>
> > >> int main(int argc,char **argv){
> > >> long res=0;
> > >> if (argc==2){
> > >>   char * bin=argv[1];
> > >>   while(*bin)
> > >>      res=res * 2 + *bin++ -'0';
> > >>   printf("input string is %s  result is %ld\n",argv[1],res);
> > >>   }
> > >> return 0;
> > >> }

> > > It's clever but unfortunately it can't be considered portable on
> > > non-ASCII systems.

> > Yes it can. '1' - '0' is guaranteed to be 1 by ISO C.

> ?

> 'some_number'-'0' is not portable since some encodings other than ASCII
> have letter characters and number characters mixed.

Then you will not have an ISO C compiler using that character set.
If you are _really_ worried about that change the line

res=res * 2 + *bin++ -'0';
to
res=res * 2 + (*bin++ =='1');
but there is no reason to do so.  :-)

Roger...

Tue, 21 Sep 2004 22:11:12 GMT
Binary to decimal

Quote:

> > Yes it can. '1' - '0' is guaranteed to be 1 by ISO C.

> 'some_number'-'0' is not portable since some encodings other than ASCII
> have letter characters and number characters mixed.

Not for ISO Standard C implementations, they don't (following quote from
latest public C99 draft Standard):

#   the 10 decimal digits
#
#       0  1  2  3  4  5  6  7  8  9

#         In  both  the
#   source and execution basic character sets, the value of each
#   character after 0 in the above list of decimal digits  shall
#   be  one  greater  than the value of the previous.

Richard

Tue, 21 Sep 2004 22:13:03 GMT

 Page 1 of 2 [ 25 post ] Go to page: [1] [2]

Relevant Pages