Base Conversion
May 2, 2017
We begin with the original task. Since this is homework for a beginning programming course, the intent is almost certainly to perform the conversion by converting the number to a string, segmenting the binary number into pairs of digits, from right to left, converting each pair from binary to quadary (is that the word? quartary? quatenary?), and converting back to a string:
(define (2to4 str) (let loop ((bits (reverse (string->list str))) (quads (list))) (cond ((null? bits) (list->string quads)) ((null? (cdr bits)) (loop (cdr bits) (cons (car bits) quads))) ((and (char=? (car bits) #\0) (char=? (cadr bits) #\0)) (loop (cddr bits) (cons #\0 quads))) ((and (char=? (car bits) #\1) (char=? (cadr bits) #\0)) (loop (cddr bits) (cons #\1 quads))) ((and (char=? (car bits) #\0) (char=? (cadr bits) #\1)) (loop (cddr bits) (cons #\2 quads))) ((and (char=? (car bits) #\1) (char=? (cadr bits) #\1)) (loop (cddr bits) (cons #\3 quads))) (else (error '2to4 "can't happen")))))
> (2to4 "11011000") "3120"
Pattern matching looks a little bit better:
(define (2to4 str) (let loop ((bits (reverse (string->list str))) (quads (list))) (list-match bits (() (list->string quads)) ((b) (loop '() (cons b quads))) ((#\0 #\0 . bs) (loop bs (cons #\0 quads))) ((#\1 #\0 . bs) (loop bs (cons #\1 quads))) ((#\0 #\1 . bs) (loop bs (cons #\2 quads))) ((#\1 #\1 . bs) (loop bs (cons #\3 quads))) (else (error '2to4 "can't happen")))))
> (2to4 "11011000") "3120"
Of course, Scheme can convert between bases natively:
(define (2to4 str) (number->string (string->number str 2) 4))
> (2to4 "11011000") "3120"
And that gives us a way to answer the extra credit task:
(define (convert in out str) (number->string (string->number str in) out))
>"3120" "3120"
You can run the program at http://ideone.com/qtTD4h.
In Python.
Up to base 64, so we cover also the Babylonians.
A web search indicates to me that the English word for base 4 is “quaternary”.
C11:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int ch;
initial: ch = getchar();
if (ch == '0') goto i0;
if (ch == '1') goto i1;
else goto end;
i0: ch = getchar();
if (ch == '0') goto i00;
if (ch == '1') goto i01;
else goto end;
i1: ch = getchar();
if (ch == '0') goto i10;
if (ch == '1') goto i11;
else goto end;
i00: putchar('0');
goto initial;
i01: putchar('1');
goto initial;
i10: putchar('2');
goto initial;
i11: putchar('3');
goto initial;
end: puts("");
exit(0);
}
MUMPS solution:
BASECHG (STR,BASE1,BASE2) ; Convert number to different base
N ACC,I,LEN,REM,REMS,STR2
S LEN=$L(STR),ACC=0
F I=1:1:LEN-1 S ACC=ACC+$E(STR,I),ACC=ACC*BASE1
S ACC=ACC+$E(STR,LEN)
I ACC<BASE2 S STR2=ACC
E D
. S I=0 F Q:ACC<BASE2 S REM=ACC#BASE2,ACC=ACC\BASE2,I=I+1,REMS(I)=REM
. S STR2=ACC,I="" F S I=$O(REMS(I),-1) Q:I="" S STR2=STR2_REMS(I)
W !,STR," (",BASE1,") = ",STR2," (",BASE2,")"
Q
—
D ^BASECHG("11011000",2,4)
11011000 (2) = 3120 (4)