Reputation: 6342
I looked at the documentation and even peeked at the C source, and I can't see why they limited the accepted radixes to 2..36. Anybody know?
Upvotes: 4
Views: 1526
Reputation: 20398
As others have pointed out, radix < 2 is troublesome to render. and there's no conventional agreement on what characters to use for radixes larger than ['0'..'9'] + ['a'..'z'], which is why the standard method doesn't support radix outside those limits.
If you really want a custom radix representation, you would need to define the alphabet of symbols to use for the digits. Here's a little module that will give you the capability.
module CustomRadix
# generate string representation of integer, using digits from custom alphabet
# [val] a value which can be cast to integer
# [digits] a string or array of strings representing the custom digits
def self.custom_radix val, digits
digits = digits.to_a unless digits.respond_to? :[]
radix = digits.length
raise ArgumentError, "radix must have at least two digits" if radix < 2
i = val.to_i
out = []
begin
rem = i % radix
i /= radix
out << digits[rem..rem]
end until i == 0
out.reverse.join
end
# can be used as mixin, eg class Integer; include CustomRadix; end
# 32.custom_radix('abcd') => "caa" (200 base 4) equiv to 32.to_s(4).tr('0123','abcd')
def custom_radix digits
CustomRadix.custom_radix self, digits
end
end
example use:
$ irb
>> require '~/custom_radix'
=> true
>> CustomRadix.custom_radix(12345,'0'..'9')
=> "12345"
>> CustomRadix.custom_radix(12345,'.-')
=> "--......---..-"
>> funny_hex_digits = ('0'..'9').to_a + ('u'..'z').to_a
=> ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "u", "v", "w", "x", "y", "z"]
>> CustomRadix.custom_radix(255, funny_hex_digits)
=> "zz"
>> class Integer; include CustomRadix; end
=> Integer
>> (2**63).custom_radix(funny_hex_digits)
=> "8000000000000000"
>> (2**64+2**63+2**62).custom_radix(funny_hex_digits)
=> "1w000000000000000"
>> base64_digits = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a << '+' << '/'
=> ["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", "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", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"]
>> 123456.custom_radix(base64_digits)
=> "eJA"
Upvotes: 8
Reputation:
How would you render a number in base 1? How would you render a number in base 37? In base 300?
It's conventional to use 0..9 and A..F for hexadecimal numbers. It's intuitive to continue using the alphabet for higher bases, but that only gets you to 36. As there are few uses (if any - I've never seen one) of higher bases, there's no convention for anything beyond that. Except perhaps for base 64, which is a quite different beast, specific to a single base, and not terribly old either. Also, there are a gazillion incompatible variants, which only reinforced my point.
And as for base 1: Unary counting exists, but it's not terribly useful, even less common in computing, and very easy to emulate (just concat n
times the same character). Besides, people probably have vastly different opinions on what that character should be.
Upvotes: 1
Reputation: 25601
I don't know anything about ruby, but I know there are 10 decimal digits plus 26 alpha digits. that's 36.
Upvotes: 2