Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the FixNum#to_s method in in Ruby only accept radixes from 2 to 36?

Tags:

ruby

radix

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?

like image 416
Justin Force Avatar asked Sep 06 '25 03:09

Justin Force


1 Answers

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"
like image 143
dbenhur Avatar answered Sep 07 '25 20:09

dbenhur