Thursday, September 29, 2011

Radix Conversion in C

In the article Formatted Strings in C I've given a few examples on how to convert between hexadecimal, octal and decimal.

Still, by using the methods described in that article you cannot convert directly to binary or a more "exotic" radix.

1.Converting to radix

Description:
A solution lays in the function char* itoa(int inputValue, char *result, int radix). This function allows you to take a number in decimal, octal or hexadecimal and convert it to a string containing the number's representation in a radix of your choosing.

Example:
#include<stdio.h>
#include<stdlib.h>

int main(void)
{
   int number = 16;
   char radix2[10], radix3[10], radix12[10];
   itoa(number,radix2,2);
   itoa(number,radix3,3);
   itoa(number,radix12,12);
   printf("\nBinary  : %s"
          "\nRadix 3 : %s"
          "\nRadix 12: %s",radix2, radix3,radix12);
   return 0;
}
/*Output:
Binary  : 10000
Radix 3 : 121
Radix 12: 14
 */
Pitfall:
The function is not ANSI, so it will not available on all compilers. Still, you can implement it by yourself. Check the useful links at the end of the article.

Observation:
This function was present in most of the old compilers (ex. Borland C) and some regard it as deprecated.

2.Converting from radix

Description:
Another option for radix conversion is the ANSI function long int strtol ( const char * str, char * endptr, int radix). The function takes as arguments:
str - a string containg numbers in the radix radix
endptr - a pointer who shall memorize the position of last character after the conversion
radix - the radix of the number who will be converted to radix 10

Simple example:
#include<stdio.h>
#include<stdlib.h>

int main(void)
{
   long x = strtol("zzzz",NULL,36);
   printf("%ld\n",x);
   return 0;
}
/*Output:
1679615
 */
In the example above, we convert the number zzzz (represented in radix 36) to a number in radix 10.

Advanced example:
#include<stdio.h>
#include<stdlib.h>

int main(void)
{
   char buffer[] = "2050 40a0b0 -110111 zzzz";
   char * ptr_end = NULL;
   long int d1, d2, d3, d4;
   d1 = strtol (buffer,&ptr_end,10);
   d2 = strtol (ptr_end,&ptr_end,16);
   d3 = strtol (ptr_end,&ptr_end,2);
   d4 = strtol (ptr_end,NULL,36);
   printf ("%ld, %ld, %ld, %ld\n", d1, d2, d3, d4);
   return 0;
}
/*Output:
2050, 4235440, -55, 1679615
 */
In this example we take full advantage of the function's capabilities. The function will use ptr_end to return a pointer after a conversion to the end of the substring containing the number who was converted.

3.Implementing a radix to radix conversion function
/*
 * Description:
 *  Performs a radix conversion
 * Parameters:
 *  oldNumber - a string containing the number who will be converted
 *  oldradix - the base of number
 *  newNumber - a string who shall contain the value of number in
 *              the radix newBase
 *  newRadix - the radix to which number will be converted
 * Preconditions:
 *  The parameters base and newBase must be between 1 and 36
 *  The number arguments can only contain '0' - '9' and 'A'-'Z' chars
 *  The number string must represent correctly the number in base "base"
 * Postcondtions
 *  The function returns:
 *      1 - Success
 *      0 - Failure because bases were not correct
 *      -1 - Failure because newNumber incorrect format
 *
 */
int DecimalRadixConvert(const char* oldNumber, int oldRadix,
                        char* newNumber, int newRadix)
{
    long data = 0L;
    char digit = 0;
    int i = 0;
    int size=strlen(oldNumber);
    char* reverseNew = NULL;
    /*Checks if base if within bounds*/
    if((oldRadix<=1 || oldRadix>36)||(newRadix<=1 || newRadix>36))
    {
        return 0;
    }
    /*Convert to base 10 from old base*/
    for(i=0;i<size;i++)
    {
        if(oldNumber[i]>='0' && oldNumber[i]<='9')
        {
            data+=(oldNumber[i]-'0')*pow(oldRadix,size-i-1);
        }
        else if(oldNumber[i]>='A' && oldNumber[i]<='Z')
        {
            data+=(oldNumber[i]-'A' + 10)*pow(oldRadix,size-i-1);
        }
        else
        {
            return -1;
        }
    }
    i=0;
    /*Convert from base 10 to new base*/
    while(data>0)
    {
        digit = data % newRadix;
        (digit<10)?(newNumber[i] = digit + '0')
                  :(newNumber[i] = digit + 'A' -10);
        data=data/newRadix;
        i++;
    }
    newNumber[i]='\0';
    /*Reverses newNumber*/
    reverseNew = (char*)(malloc(sizeof(char)*strlen(newNumber)));
    size = strlen(newNumber);
    for(i=0; i<size; i++)
    {
        reverseNew[i] = newNumber[size-1-i];
    }
    reverseNew[size]='\0';
    newNumber = reverseNew;
    return 1;
}
The function above converts number to radix 10 and then converts the result the the specified newRadix radix.

Example:
#include<stdio.h>
#include<stdlib.h>

int DecimalRadixConvert(const char* oldNumber, int oldRadix,
                           char* newNumber, int newRadix);

int main(void)
{
   char data[15]="1233";
   char data2[15];
   /*Converts from base 5 to base 3*/
   DecimalRadixConvert(data,5,data2,3);
   printf("\nRadix 3: %s\nRadix 5: %s",data2,data);
   return 0;
}
/*Output:
Radix3: 20222
Radix5: 1233
 */
Useful links:
itoa implementation
Radix Conversion Applet

No comments:

Post a Comment

Got a question regarding something in the article? Leave me a comment and I will get back at you as soon as I can!

Related Posts Plugin for WordPress, Blogger...
Recommended Post Slide Out For Blogger