From Decimal to Base 36

The next step in my Base 36 series is to translate a decimal value into its base 36 representation. In last week’s Lesson, code was presented to build a powers table and slice a decimal value into its base 36 components. This Lesson completes the task with a function, base36_sting() to build and output a base 36 value.

To craft a base 36 number, the various powers of 36 must be stored in an array based on the value translated. For example, for the value 12,345 the base 36 value is 9IX, as shown in Figure 1.

Figure 1. How the base 36 value 9IX translates into decimal.

This new array stores values for their power positions, one element for each power of 36:

9 in the 1,269 (362) position
I in the 36 (36(1) position
X in the 1 (360) position.

Of course, this array holds values, not the base 36 characters:

b36_values[2] = 11,664 (9 × 1,269)
b36_values[1] = 648 (I × 36)
b36_values[0] = 33 (X × 1)

The base36_string() function translates these values into characters, 0 to 9 and A to Z. Here is my code:

2025_07_12-Lesson-a.c

#include <stdio.h>

#define BASE36_MAX 36
#define SIZE 10

/* generate a base 36 value */
char *base36_string(int *v)
{
    static char b36_string[SIZE+1];
    int x,y;

    /* build base 36 string */
    y = SIZE-1;
    for( x=0; x<SIZE-1; x++ )
    {
        if( *(v+y)<10 )
            b36_string[x] = *(v+y)+'0';
        else
            b36_string[x] = *(v+y)+'A'-10;
        y--;
    }
    b36_string[x] = '\0';

    return(b36_string);
}

int main()
{
    long b36_powers[SIZE];
    int b36_values[SIZE];
    int x,d;

    /* prompt for input */
    printf("Enter base 10 value: ");
    scanf("%d",&d);
    if( d<1 )
    {
        puts("Enter a value larger than zero");
        return 1;
    }

    /* build the powers table */
    for( x=0; x<SIZE; x++ )
        b36_powers[x] = x ? b36_powers[x-1]*BASE36_MAX : 1;

    /* translate the decimal value */
    for( x=SIZE-2; x>=0; x-- )
        b36_values[x+1] = ( d % b36_powers[x+1])/ b36_powers[x];

    /* output the result in base 36 */
    printf("%s\n",base36_string(b36_values));

    /* clean-up */
    return 0;
}

The main() function duplicates some code from last week’s Lesson, but with an extra array, b36_values[]. The second for loop fills this array:

for( x=SIZE-2; x>=0; x-- )
    b36_values[x+1] = ( d % b36_powers[x+1])/ b36_powers[x];

The array is passed to the base36_string() function and output directly in the next printf() statement.

In the base36_string() function, the array is passed as a pointer, v. A for loop in the function works through the static char string b36_string[]. Variable y processes the passed array backwards, plucking out powers of 36 and filling the b36_string[] array with a base 36 value, 0 through 9 and A through Z. The string is capped with a null character and returned for output.

Here’s a sample run:

Enter base 10 value: 12345
0000009IX

The function properly returns a base 36 string — but the string is padded with leading zeros. I thought of several ways to deal with them.

First, I could allocate the string as a pointer instead of a static char array. Then the pointer is returned referencing the first non-zero character in the string. But by allocating a pointer, another problem is created: freeing the pointer. Not only is the pointer no longer referencing its true base, but every time that the function is called more pointers are created. Especially when a base 36 string is used directly, as shown in the code above, freeing it becomes an issue.

Second, I thought of creating another array to return instead, copying the relevant characters into this second array. This solution works, but seems clunky to me.

Third, I thought of shuffling characters in the existing b36_string[] array, which is what I ended up doing. You can click here to view this addition on GitHub.

In next week’s Lesson, I present a function to translate a base 36 string into its decimal value.

Leave a Reply