💾 Archived View for thrig.me › blog › 2022 › 10 › 11 › 10.gmi captured on 2023-04-19 at 22:58:21. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-03-20)
-=-=-=-=-=-=-
The number 10 is a bit tricky; it exists in every base. This is mostly a concern in systems where one can change the base (lojban, using ju'u) or worse where changing the base changes how the entire system behaves, which in turn can make changing the base again difficult. Forth implementations may have this, um, feature. Charles Moore took to setting the base at the top of the block, for some reason or another.
2 base ! \ 2 address-of-base write-value 16 base ! \ error! -- 16 is not a known word
16 is not a valid number in base 2. Solutions here include pre-loading the stack with the necessary values (difficult), converting the (decimal) 16 to a form suitable for the current base, or to use a literal numeric form that is always in a particular base or includes the base along with the value. Common LISP supports this last form; other languages tend to accrue such in non-standard or incremental ways, if at all.
$ sbcl --noinform --eval '(progn (format t "~d~%" #2R10000) (quit))' 16 $ sbcl --noinform --eval '(progn (format t "~d~%" #b10000) (quit))' 16 $ cfu 'printf("%d\n", 0b10000)' ... warning: binary integer literals are a GNU extension printf("%d\n", 0b10000); ^ 1 warning generated. 16
Conversion to a particular base might run something along the lines of:
#!/usr/bin/env perl # # 10 - add 10 to the stack in base 2, 8, 10, and 16 use 5.32.0; use warnings; use experimental 'signatures'; use Carp 'croak'; use Language::Eforth; our $f = Language::Eforth->new; my $base = 10; for my $newbase (qw(2 8 10 16)) { my $enc = inbase( $newbase, $base ); $f->eval("$enc base !\n10\n"); $base = $newbase; } # back to base 10 - embed supports $hexnumber for literal input, # probably better than the inbase conversion (but less educational) $f->eval( '$A base !' . " .s\n" ); # this could also be done with an "alphabet", see Number::AnyBase; ANS # FORTH and Common LISP however restrict the base to 2..36 sub inbase ( $n, $base = 10 ) { croak "N must be positive" if $n < 0; croak "base must be in the range 2..36" if $base < 2 or $base > 36; return $n if $base == 10; my $str = ''; while (1) { my $mod = $n % $base; $n = int( $n / $base ); # PORTABILITY not everything uses ASCII $mod = chr( 55 + $mod ) if $mod > 9; $str = $mod . $str; last if $n == 0; } return $str; }
tags #lisp #perl #forth