index: release v1.18 with only altgr index linked
[sheet.git] / base.plp
1 <(common.inc.plp)><:
2
3 Html({
4         title => 'number bases',
5         version => '1.2',
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 my %RADIXNAME = (
19          2 => 'binary',
20          3 => 'ternary',
21         #4 => 'quaternary',
22         #5 => 'quinary',
23          6 => 'senary',
24          8 => 'octal',
25         #9 => 'nonary',
26         10 => 'decimal',
27         12 => 'dozenal', # duodecimal
28         16 => 'hexadecimal',
29         20 => 'vigesimal',
30         #36 => 'double-senary',
31         60 => 'sexagesimal',
32         #64 => 'double-octal',
33 );
34 :>
35 <h1>Number bases</h1>
36
37 <h2>Radix economy</h2>
38 <table class=mapped>
39 <:
40 sub showcolhead {
41         print '<col>';
42         my @spans;
43         $spans[ $_ > 10 ]++ for @_;
44         print "<colgroup span=$_>" for @spans;
45         print '<thead><tr><th>';
46         for (@_) {
47                 print '<th>', $_ < 36 ? $char[$_] : $char[35].'+'.$char[$_ - 35];
48                 print " <small>($_)</small>" for join(', ',
49                         $RADIXNAME{$_} // (),
50                         $_ >= 10 ? "base$_" : (),
51                 ) || ();
52         }
53         say '</thead>';
54 }
55
56 sub radix_economy {
57         my ($val, $radix) = @_;
58         return $radix * int(log($val) / log($radix) + 1);
59 }
60
61 use List::Util 'sum';
62
63 showcolhead(@morecols);
64
65 for my $max (100, 255, 1024) {
66         print '<tr><th>⍳', $max;
67         for my $radix (@morecols) {
68                 printf '<td style="text-align:right">%.1f',
69                         sum(map { radix_economy($_, $radix) } 1 .. $max) / $max;
70         }
71 }
72 :></table>
73
74 <h2>Reciprocal fractions (n⁻¹)</h2>
75 <table class=mapped>
76 <:
77 use Math::BigFloat;
78
79 my $count = 40;
80 my $places = $count<<1;
81
82 sub showfrac {
83         my ($num, $radix) = @_;
84
85         my $out = '';
86         my $class = '';
87         my $zeros = 0;
88
89 ADD_DIGITS:
90         for my $place (1 .. $places) {
91                 # add a digit in requested base (left shift)
92                 $out .= $char[ $num->blsft(1, $radix) ];
93                 $num->bmod(1) or do {
94                         # no remaining fractional part
95                         $class = $out eq '1' ? 'l5' : $place == 1 ? 'l4' : 'l3';
96                         last;
97                 };
98                 $zeros++ if $out =~ /^0+$/;
99
100                 for my $check ($zeros .. length($out)>>1) {
101                         if (substr($out, -$check) eq substr($out, -$check*2, $check)) {
102                                 $class = $check == 1 ? 'l2' : 'l1';
103                                 substr($out, -$check) = '';
104                                 substr($out, -$check, 0) = '<span style="text-decoration:overline">';
105                                 $check .= '</span>';
106                                 last ADD_DIGITS;
107                         }
108                 }
109         }
110         printf '<td%s style="text-align:left">%s', $class && qq( class="$class"), $out;
111 }
112
113 showcolhead(@cols);
114
115 for my $n (2 .. $count) {
116         print '<tbody>' if $n % 8 == 1;
117         print '<tr>';
118         print '<th>', $n;
119         for my $radix (@cols) {
120                 my $accuracy = int($places * log($radix) / log(10));
121                 Math::BigFloat->accuracy($accuracy);
122                 showfrac(scalar Math::BigFloat->new(1)->bdiv($n, $accuracy+1), $radix);
123         }
124         say '';
125 }
126
127 :></table>
128
129 <hr>
130
131 <h2>Duplication (2ⁿ)</h2>
132 <table class=mapped>
133 <:
134 sub showint {
135         my ($int, $radix) = @_;
136         my @digits;
137         while ($int >= 1) {
138                 push @digits, $char[$int % $radix];
139                 $int /= $radix;
140         }
141         splice @digits, 3 * $_, 0, '&nbsp;' for reverse 1 .. @digits/3;
142         return join '', reverse @digits;
143 }
144
145 @cols = grep { not $_ ~~ [2,8,16] } @cols, 36;
146 showcolhead(@cols);
147
148 for my $n (0, 3 .. 16, 0, 18, 20, 24, 30, 32, 36, 40, 48, 50, 60, 64) {
149         if (!$n) {
150                 print '<tbody>';
151                 next;
152         }
153         print '<tr>';
154         print '<th>', $n;
155         for my $radix (@cols) {
156                 print '<td style="text-align:right">', showint(2 ** $n, $radix);
157         }
158         say '<th>', {
159                  4 => 'nibble',
160                  8 => 'octet',
161                 16 => '2o',
162                 24 => '3o',
163                 32 => '4o',
164                 40 => '5o, Tebi',
165                 48 => '6o',
166                 64 => 'o²',
167                 10 => 'kibi',
168                 20 => 'Mebi',
169                 30 => 'Gibi',
170                 50 => 'Pebi',
171                 60 => 'Exbi',
172                 70 => 'Zebi',
173                 80 => 'Yobi',
174         }->{$n} // '';
175 }
176
177 :></table>