charset: check ucplanes for modification date
[sheet.git] / base.plp
1 <(common.inc.plp)><:
2
3 Html({
4         title => 'number bases',
5         version => '1.1',
6         description => [
7                 "Cheat sheets summarising various software programs and standards.",
8         ],
9         keywords => [qw'
10                 sheet cheat reference software overview summary help keyboard map unicode
11         '],
12         stylesheet => [qw'light dark circus mono red'],
13 });
14
15 my @cols = (2, 6, 8, 9, 10, 12, 16, 18, 20);
16 my @morecols = (2 .. 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 64);
17 my @char = (0..9, 'A'..'Z', 'a'..'z');
18 :>
19 <h1>Number bases</h1>
20
21 <h2>Radix economy</h2>
22 <table>
23 <:
24 sub radix_economy {
25         my ($val, $radix) = @_;
26         return $radix * int(log($val) / log($radix) + 1);
27 }
28
29 use List::Util 'sum';
30 print '<tr><th>';
31 print '<th>', $_ for @morecols;
32 for my $max (100, 255, 1024) {
33         print '<tr><th>⍳', $max;
34         for my $radix (@morecols) {
35                 printf '<td style="text-align:right">%.1f',
36                         sum(map { radix_economy($_, $radix) } 1 .. $max) / $max;
37         }
38 }
39 :></table>
40
41 <h2>Reciprocal fractions (n⁻¹)</h2>
42 <table>
43 <:
44 print '<tr><th>';
45 print '<th>', $_ for @cols;
46
47 use Math::BigFloat;
48
49 my $count = 40;
50 my $places = $count<<1;
51
52 sub showfrac {
53         my ($num, $radix) = @_;
54
55         my $out = '';
56         my $class = '';
57         my $zeros = 0;
58
59 ADD_DIGITS:
60         for my $place (1 .. $places) {
61                 # add a digit in requested base (left shift)
62                 $out .= $char[ $num->blsft(1, $radix) ];
63                 $num->bmod(1) or do {
64                         # no remaining fractional part
65                         $class = $out eq '1' ? 'l5' : $place == 1 ? 'l4' : 'l3';
66                         last;
67                 };
68                 $zeros++ if $out =~ /^0+$/;
69
70                 for my $check ($zeros .. length($out)>>1) {
71                         if (substr($out, -$check) eq substr($out, -$check*2, $check)) {
72                                 $class = $check == 1 ? 'l2' : 'l1';
73                                 substr($out, -$check) = '';
74                                 substr($out, -$check, 0) = '<span style="text-decoration:overline">';
75                                 $check .= '</span>';
76                                 last ADD_DIGITS;
77                         }
78                 }
79         }
80         printf '<td%s style="text-align:left">%s', $class && qq( class="$class"), $out;
81 }
82
83 for my $n (2 .. $count) {
84         print '<tr>';
85         print '<th>', $n;
86         for my $radix (@cols) {
87                 my $accuracy = int($places * log($radix) / log(10));
88                 Math::BigFloat->accuracy($accuracy);
89                 showfrac(scalar Math::BigFloat->new(1)->bdiv($n, $accuracy+1), $radix);
90         }
91 }
92
93 :></table>
94
95 <hr>
96
97 <h2>Duplication (2ⁿ)</h2>
98 <table>
99 <:
100 sub showint {
101         my ($int, $radix) = @_;
102         my @digits;
103         while ($int >= 1) {
104                 push @digits, $char[$int % $radix];
105                 $int /= $radix;
106         }
107         splice @digits, 3 * $_, 0, '&nbsp;' for reverse 1 .. @digits/3;
108         return join '', reverse @digits;
109 }
110
111 @cols = grep { not $_ ~~ [2,8,16] } @cols, 36;
112 print '<tr><th>';
113 print '<th>', $_ for @cols;
114
115 for my $n (3 .. 16, 18, 20, 24, 30, 32, 36, 40, 48, 50, 60, 64) {
116         print '<tr>';
117         print '<th>', $n;
118         for my $radix (@cols) {
119                 print '<td style="text-align:right">', showint(2 ** $n, $radix);
120         }
121         print '<th>', {
122                  4 => 'nibble',
123                  8 => 'octet',
124                 16 => '2o',
125                 24 => '3o',
126                 32 => '4o',
127                 40 => '5o, Tebi',
128                 48 => '6o',
129                 64 => 'o²',
130                 10 => 'kibi',
131                 20 => 'Mebi',
132                 30 => 'Gibi',
133                 50 => 'Pebi',
134                 60 => 'Exbi',
135                 70 => 'Zebi',
136                 80 => 'Yobi',
137         }->{$n} // '';
138 }
139
140 :></table>