Почему метод FixNum # to_s в Ruby принимает только радиусы от 2 до 36? - PullRequest
3 голосов
/ 22 марта 2012

Я посмотрел на документацию и даже заглянул в источник C, и я не могу понять, почему они ограничили принятые радиусы до 2..36. Кто-нибудь знает?

Ответы [ 3 ]

7 голосов
/ 23 марта 2012

Как уже отмечали другие, основание <2 проблематично отображать. и нет общепринятого соглашения о том, какие символы использовать для осей, больших чем ['0' .. '9'] + ['a' .. 'z'], поэтому стандартный метод не поддерживает основание за пределами этих пределов . </p>

Если вы действительно хотите, чтобы пользовательское представление основывалось на осях, вам необходимо определить алфавит символов, который будет использоваться для цифр. Вот небольшой модуль, который даст вам возможность.

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

пример использования:

$ 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"
2 голосов
/ 22 марта 2012

Я ничего не знаю о ruby, но я знаю, что есть 10 десятичных цифр плюс 26 буквенных цифрэто 36.

1 голос
/ 22 марта 2012

Как бы вы отобразили число в базе 1?Как бы вы отобразили число в базе 37?В базе 300?

Обычно используется 0,9 и A..F для шестнадцатеричных чисел.Интуитивно продолжать использовать алфавит для более высоких оснований, но это только приводит вас к 36. Поскольку существует мало применений (если есть - я никогда не видел) более высоких оснований, не существует соглашения для чего-либо кроме этого.За исключением, возможно, для базы 64, которая является совершенно другим зверем, специфичным для одной базы, и не очень старым.Кроме того, существует несколько миллиардов несовместимых вариантов, которые только укрепили мою точку зрения.

И что касается базы 1: унарный подсчет существует, но он не очень полезен, даже менее распространен в вычислениях, и его очень легко эмулировать (простоconcat n раз один и тот же символ).Кроме того, люди, вероятно, имеют совершенно разные мнения о том, каким должен быть этот персонаж.

...