base: include base-5 in economy comparison
[sheet.git] / base.plp
index cba5242966a6f622a933cb027965e6fc05491709..3a89a53de6979de2a05417ab84620f5698ad353d 100644 (file)
--- a/base.plp
+++ b/base.plp
@@ -1,8 +1,8 @@
 <(common.inc.plp)><:
 
 Html({
-       title => 'fractions',
-       version => 'v1.0',
+       title => 'number bases',
+       version => 'v1.1',
        description => [
                "Cheat sheets summarising various software programs and standards.",
        ],
@@ -12,22 +12,44 @@ Html({
        stylesheet => [qw'light dark circus mono red'],
 });
 
+my @cols = (2, 6, 8, 9, 10, 12, 16, 18, 20);
+my @morecols = (2 .. 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 64);
+my @char = (0..9, 'A'..'Z', 'a'..'z');
 :>
-<h1>Fractions</h1>
+<h1>Number bases</h1>
 
+<h2>Radix economy</h2>
 <table>
 <:
-use Math::BigFloat;
+sub radix_economy {
+       my ($val, $radix) = @_;
+       return $radix * int(log($val) / log($radix) + 1);
+}
 
-my @cols = (2, 6, 8, 9, 10, 12, 16, 18, 20);
-my $count = 40;
+use List::Util 'sum';
+print '<tr><th>';
+print '<th>', $_ for @morecols;
+for my $max (100, 255, 1024) {
+       print '<tr><th>⍳', $max;
+       for my $radix (@morecols) {
+               printf '<td style="text-align:right">%.1f',
+                       sum(map { radix_economy($_, $radix) } 1 .. $max) / $max;
+       }
+}
+:></table>
+
+<h2>Reciprocal fractions (n⁻¹)</h2>
+<table>
+<:
 print '<tr><th>';
 print '<th>', $_ for @cols;
 
-my @char = (0..9, 'A'..'Z', 'a'..'z');
+use Math::BigFloat;
+
+my $count = 40;
 my $places = $count<<1;
 
-sub shownum {
+sub showfrac {
        my ($num, $radix) = @_;
 
        my $out = '';
@@ -36,8 +58,10 @@ sub shownum {
 
 ADD_DIGITS:
        for my $place (1 .. $places) {
+               # add a digit in requested base (left shift)
                $out .= $char[ $num->blsft(1, $radix) ];
                $num->bmod(1) or do {
+                       # no remaining fractional part
                        $class = $out eq '1' ? 'l5' : $place == 1 ? 'l4' : 'l3';
                        last;
                };
@@ -62,9 +86,56 @@ for my $n (2 .. $count) {
        for my $radix (@cols) {
                my $accuracy = int($places * log($radix) / log(10));
                Math::BigFloat->accuracy($accuracy);
-               shownum(scalar Math::BigFloat->new(1)->bdiv($n, $accuracy+1), $radix);
+               showfrac(scalar Math::BigFloat->new(1)->bdiv($n, $accuracy+1), $radix);
        }
 }
 
 :></table>
 
+<hr>
+
+<h2>Duplication (2ⁿ)</h2>
+<table>
+<:
+use 5.010;
+sub showint {
+       my ($int, $radix) = @_;
+       my @digits;
+       while ($int >= 1) {
+               push @digits, $char[$int % $radix];
+               $int /= $radix;
+       }
+       splice @digits, 3 * $_, 0, '&nbsp;' for reverse 1 .. @digits/3;
+       return join '', reverse @digits;
+}
+
+@cols = grep { not $_ ~~ [2,8,16] } @cols, 36;
+print '<tr><th>';
+print '<th>', $_ for @cols;
+
+for my $n (3 .. 16, 18, 20, 24, 30, 32, 36, 40, 48, 50, 60, 64) {
+       print '<tr>';
+       print '<th>', $n;
+       for my $radix (@cols) {
+               print '<td style="text-align:right">', showint(2 ** $n, $radix);
+       }
+       print '<th>', {
+                4 => 'nibble',
+                8 => 'octet',
+               16 => '2o',
+               24 => '3o',
+               32 => '4o',
+               40 => '5o, Tebi',
+               48 => '6o',
+               64 => 'o²',
+               10 => 'kibi',
+               20 => 'Mebi',
+               30 => 'Gibi',
+               50 => 'Pebi',
+               60 => 'Exbi',
+               70 => 'Zebi',
+               80 => 'Yobi',
+       }->{$n} // '';
+}
+
+:></table>