Why (73).toString(36) returns 21 and (0.73).toString(36) returns 0.qa2voha2volfpsnhmyhqia4i and not 0.21?
4 Answers
That's because floats are stored as binary fractions (a number divided by a power of 2), and 73/100 cannot be expressed as a non-repeating fraction in binary. Thus internally, it's storing a value close to 0.73 but not exactly equal. That's why you get so many digits in the toString() method.
73/100 also can't be expressed as a non-repeating fraction in base 36. In general, for a fraction a/b you can only get a fixed number of digits after the decimal point in a given base x if you can reduce a/b to the form c/(x^n) for some integers c and n.
73 = 2 x 36 + 1 0.73 = 26/36 + 10/(36 * 36) + ... Like in hex we have 0, ..., 9, a, b, c, d, e, f with f being the 16th digit, in 36-base system we have 0, 1, ..., 9, ..., q, ..., z with q being the 26th digit and a the 10th digit.
The cause of this issue lies in that 0.21 in 36-base is 36 times smaller than 21 in 36-base and not 10 times.
Numbers of 36 base will have 36 digits: from 0 to z.
73 in base 10 = 21 in base 36, because 1 + 2 * 36 = 73.
Float numbers are not calculated that way at all. (0.5).toString(2) is not 0.101, but 0.1. 0.73 calculated converted to any base will return a number that would be exactly 73% way from 0 to 1.
number => Alphabet
let childs = []; for (let i = 10; i < 36; i++) { childs.push( i.toString(36) ); } // 26 childs; // (26) ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]