/*  C program CVTBASEN.C -- converts a decimal number to another base */

/*  Copyright Dave Schnee, 1994  */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

main()

{
char    numalph[92] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      "abcdefghijklmnopqrstuvwxyz!@#$%^&*()~`-=_+|}{][';/:?><";
char    instring[128];
int     base,   maxpower,       output, i,      scanres;
long double  decinput,  dvalue;
double  keyinput;

retrybase:
printf("Please specify the output number base\n");
printf("  (a number from 2 through 91 or zero==>quit):\n");
if ((scanres = scanf("%s", instring)) == EOF) exit(3);
if ( scanres == 0 ) goto retrybase;
base    = atoi( instring );
if ( base == 0 ) exit(0);
if ( ( base < 2 ) || ( base > 91 ) ) goto retrybase;

if ( base > 36 ) printf("\nThe digits to be used are: %s\n\n", numalph );

retryinput:
printf("Enter the input number in decimal\n");
printf("  (or enter zero to change the base):\n");
if ((scanres = scanf("%s", instring)) == EOF) exit(3);
if ( scanres == 0 ) goto retryinput;
keyinput= atof( instring );
if ( (decinput=keyinput) == 0.0 ) goto retrybase;

printf("The result, in base %d, is:\n", base);

/* To convert decimal to another number base ............... */

/*  step 1
	Find the maximum # of digits to the left of the radix point
	by computing the logarithm of the decimal input to the base radix.

   (note:)
				    (log to the base e of INPUT)
   log to the base radix of INPUT = ----------------------------
				    (log to the base e of radix)         */

maxpower = log ( (double) decinput) / log ( (double) base) + .00001;
if ( maxpower < 0 )     maxpower = 0;  /* minimum is "units" position */

/*  step 2
	Find the value of the highest power of the radix needed         */

dvalue   = pow ( (double) base, (double) maxpower);

/*  steps 3-->n
	Peel the next higher digit (for the base radix) off the high-order
	part of the remaining number (by dividing the remaining number by
	the current power of the radix and keeping only the integer part of
	the quotient).  Print the output digit.  Subtract that digit's
	worth of the current power of the radix from the remaining number
	and divide the current power of the radix by the radix.         */

i       = 0;

divide:

output  = decinput / dvalue;
printf("%c", numalph[output]);
decinput -= (output * dvalue);
if (i++ == maxpower) printf(".");
dvalue /= (long double) base;
if ( ( (decinput > 0.0) || (dvalue >= 1.0) ) && (i < 100) )  goto divide;

printf("\n");
goto retryinput;

}
