It's late. That was the hardest thing I think I've ever tried to code. Was it worth it? Hell yeah.
Base converter up to base +-64 using only integer arithmetic, and it calculates the buffer size first. Bases greater than ip-like form should be a piece of cake. Negative bases less than -64? F***.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* tobase( int, int );
unsigned int ilog2( unsigned int );
int py_div( int, int );
int py_mod( int, int );
int main( int argc, char* argv[] )
{
int ret;
int n;
int base;
char* t;
if ( argc != 3 )
{
puts( "Usage: tobase NUMBER BASE" );
ret = 1;
}
else
{
n = atoi( argv[1] );
base = atoi( argv[2] );
t = tobase( n, base );
if ( t == NULL )
{
ret = 2;
puts( "Error." );
}
else
{
puts( t );
free( t );
ret = 0;
}
}
return ret;
}
char* tobase( int i, int base )
{
const char symbols[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
char* ret;
int lbn;
int neg;
int c;
int rem;
if ( ( ( base > -2 ) && ( base < 2 ) ) || ( base > 64 ) || ( base < -64 ) )
{
ret = NULL;
}
else if ( base < 0 )
{
if ( i < 0 )
{
neg = 1;
lbn = ( ilog2( -i * -base + -i + base ) / ilog2( -base ) );
}
else
{
neg = 0;
lbn = ( ilog2( i * -base + i + base ) / ilog2( -base ) );
}
if ( lbn % 2 == neg )
{
lbn++;
}
c = lbn;
ret = ( char* )malloc( c + 1 );
ret[c--] = '0';
do
{
rem = py_mod(i, base);
i = py_div(i, base);
if ( rem < 0 )
{
i++;
rem -= base;
}
ret[c--] = symbols[rem];
} while ( i );
}
else
{
if ( i < 0 )
{
neg = 1;
i = -i;
}
else
{
neg = 0;
}
lbn = ilog2( i ) / ilog2( base ) + 1;
c = lbn + neg;
ret = ( char* )malloc( ( c + 1 ) * sizeof( char ) );
ret[c--] = '0';
if ( neg )
{
ret[0] = '-';
}
do
{
ret[c--] = symbols[i % base];
i /= base;
}
while ( i );
}
return ret;
}
unsigned int ilog2( unsigned int n )
{
unsigned int ret;
if (n == 0)
return -1;
ret = 0;
if (n >= (1 <<16)) { n >>= 16; ret += 16; }
if (n >= (1 << 8)) { n >>= 8; ret += 8; }
if (n >= (1 << 4)) { n >>= 4; ret += 4; }
if (n >= (1 << 2)) { n >>= 2; ret += 2; }
if (n >= (1 << 1)) { ret += 1; }
return ret;
}
int py_div( int a, int b )
{
int ret;
ret = ( a - py_mod( a, b ) ) / b;
return ret;
}
int py_mod( int a, int b )
{
int ret;
if ( a < 0 )
{
if ( b < 0 )
{
ret = -((-a) % (-b));
}
else
{
ret = a % b;
}
}
else
{
if ( b < 0 )
{
ret = a % -b;
if ( ret )
{
ret += b;
}
}
else
{
ret = a % b;
}
}
return ret;
}
Only bases it won't do are those that can't be expressed as integers, and 1, 0 and -1. Not sure if they are defined at all though. Base 1 is just a tally right? 11111
etc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char symbols[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
char* tobase( int, int );
char* tobase_neg( int, int );
char* tobase_pos( int, int );
char* tobase_neg64( int, int );
char* tobase_pos64( int, int );
unsigned int ilog2( unsigned int );
int py_div( int, int );
int py_mod( int, int );
int main( int argc, char* argv[] )
{
int ret;
int n;
int base;
char* t;
if ( argc != 3 )
{
puts( "Usage: tobase NUMBER BASE" );
ret = 1;
}
else
{
n = atoi( argv[1] );
base = atoi( argv[2] );
printf( "%i to base %in", n, base );
t = tobase( n, base );
if ( t == NULL )
{
ret = 2;
puts( "Error." );
}
else
{
puts( t );
free( t );
ret = 0;
}
}
return ret;
}
char* tobase_neg( int i, int base )
{
char* ret;
int lbn;
char** parts;
int n;
int l;
int rem;
if ( i < 0 )
{
lbn = ( ilog2( -i * -base + -i + base ) / ilog2( -base ) );
if ( lbn % 2 != 0 )
{
lbn++;
}
}
else
{
lbn = ( ilog2( i * -base + i + base ) / ilog2( -base ) );
if ( lbn % 2 == 0 )
{
lbn++;
}
}
parts = ( char** )malloc( sizeof( char* ) * lbn );
n = lbn - 1;
do
{
rem = py_mod(i, base);
i = py_div(i, base);
if ( rem < 0 )
{
i++;
rem -= base;
}
l += asprintf( &parts[n--], "%i", rem );
} while ( i );
l += lbn;
ret = ( char* )malloc( l + 1 );
ret[0] = '0';
for ( n = 0; n < lbn; n++ )
{
strcat( ret, parts[n] );
if ( n + 1 < lbn )
{
strcat( ret, "." );
}
free( parts[n] );
}
free( parts );
return ret;
}
char* tobase_pos( int i, int base )
{
char* ret;
int lbn;
int neg;
char** parts;
int n;
int l;
if ( i < 0 )
{
neg = 1;
i = -i;
}
else
{
neg = 0;
}
lbn = ilog2( i ) / ilog2( base ) + 1;
parts = ( char** )malloc( sizeof( char* ) * lbn );
n = lbn - 1;
do
{
l += asprintf( &parts[n--], "%i", i % base );
i /= base;
}
while ( i );
l += lbn + neg;
ret = ( char* )malloc( l + 1 );
if ( neg )
{
ret[0] = '-';
ret[1] = '0';
}
else
{
ret[0] = '0';
}
for ( n = 0; n < lbn; n++ )
{
strcat( ret, parts[n] );
if ( n + 1 < lbn )
{
strcat( ret, "." );
}
free( parts[n] );
}
free( parts );
return ret;
}
char* tobase_neg64( int i, int base )
{
char* ret;
int lbn;
int neg;
int c;
int rem;
if ( i < 0 )
{
neg = 1;
lbn = ( ilog2( -i * -base + -i + base ) / ilog2( -base ) );
}
else
{
neg = 0;
lbn = ( ilog2( i * -base + i + base ) / ilog2( -base ) );
}
if ( lbn % 2 == neg )
{
lbn++;
}
c = lbn;
ret = ( char* )malloc( c + 1 );
ret[c--] = '0';
do
{
rem = py_mod(i, base);
i = py_div(i, base);
if ( rem < 0 )
{
i++;
rem -= base;
}
ret[c--] = symbols[rem];
} while ( i );
return ret;
}
char* tobase_pos64( int i, int base )
{
char* ret;
int lbn;
int neg;
int c;
if ( i < 0 )
{
neg = 1;
i = -i;
}
else
{
neg = 0;
}
lbn = ilog2( i ) / ilog2( base ) + 1;
c = lbn + neg;
ret = ( char* )malloc( ( c + 1 ) * sizeof( char ) );
ret[c--] = '0';
if ( neg )
{
ret[0] = '-';
}
do
{
ret[c--] = symbols[i % base];
i /= base;
}
while ( i );
return ret;
}
char* tobase( int i, int base )
{
char* ret;
if ( base < -64 )
{
ret = tobase_neg( i, base );
}
else if ( base <= -2 )
{
ret = tobase_neg64( i, base );
}
else if ( base > 64 )
{
ret = tobase_pos( i, base );
}
else if ( base >= 2 )
{
ret = tobase_pos64( i, base );
}
else
{
ret = NULL;
}
return ret;
}
unsigned int ilog2( unsigned int n )
{
unsigned int ret;
if (n == 0)
return -1;
ret = 0;
if (n >= (1 <<16)) { n >>= 16; ret += 16; }
if (n >= (1 << 8)) { n >>= 8; ret += 8; }
if (n >= (1 << 4)) { n >>= 4; ret += 4; }
if (n >= (1 << 2)) { n >>= 2; ret += 2; }
if (n >= (1 << 1)) { ret += 1; }
return ret;
}
int py_div( int a, int b )
{
int ret;
ret = ( a - py_mod( a, b ) ) / b;
return ret;
}
int py_mod( int a, int b )
{
int ret;
if ( a < 0 )
{
if ( b < 0 )
{
ret = -((-a) % (-b));
}
else
{
ret = a % b;
}
}
else
{
if ( b < 0 )
{
ret = a % -b;
if ( ret )
{
ret += b;
}
}
else
{
ret = a % b;
}
}
return ret;
}