2012-03-22 76 views
2

我查看了文檔,甚至偷看了C源代碼,我看不出爲什麼他們將可接受的基數限制爲2..36。有人知道嗎?爲什麼Ruby中的FixNum#to_s方法只接受2到36的基數?

+1

@muistooshort基地1存在,做過一個理貨清單?還是計算一些測試跑步者爲成功測試產生的點數?對於這個問題,可能有一個基地'1/2'和更瘋狂的東西(基地'phi'任何人?)。 – delnan 2012-03-22 17:46:37

回答

6

正如其他人所指出的,麥冬< 2是麻煩的渲染。而且對於大於['0','9'] + ['a','z']的基數,使用什麼字符沒有常規協議,這就是爲什麼標準方法不支持超出這些限制的基數。

如果你真的想要一個自定義的基數表示,你需要定義符號的字母來使用的數字。這裏有一個小模塊,可以給你這個能力。

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" 
+0

我敢肯定,在36到64之間缺少基數約定是2..36基數限制的原因。接受的答案爲優秀模塊和例子用法。謝謝! – 2012-03-23 15:33:50

+1

我怎麼反思這個,想把''eJA''變回'123456'? – Zac 2016-10-23 14:34:52

+1

@zac它是atoi與自定義字母表。對於每個字符,將累加器乘以基數(字母大小),將字符翻譯爲數字並添加到累加器。 – dbenhur 2016-10-24 22:49:46

2

我不知道紅寶石什麼,但我知道有10個十進制數字加上26個字母數字。這是36.

+0

這當然可能是原因,但如果區分大小寫,則有46個字母數字字符。這實際上是因爲我想要生成一組46個字符的隨機31個字符的字符串,並且對此產生了「31.times.inject(''){| i |我<< rand(46).to_s(46)}'不起作用。 – 2012-03-22 17:44:30

+1

@sidewaysmilk但是十六進制數字幾乎普遍不區分大小寫,並且改變高位基數會非常不一致。 – delnan 2012-03-22 17:48:41

+0

然後,我建議你使用base-64編碼。 – BlueMonkMN 2012-03-22 17:49:14

1

你將如何渲染基數爲1的數字?你將如何渲染基數爲37的數字?在基地300?

對於十六進制數字,通常使用0..9和A..F。繼續使用字母表代替更高的基數是直觀的,但這隻能讓你達到36個。由於基數較少的用途(如果有的話 - 我從未見過),除此之外沒有任何約定。除了基地64,這是一個非常不同的野獸,特定於一個基地,而不是非常老。此外,還有一個巨大的不兼容變體,這隻會加強我的觀點。基礎1:存在一元計數,但它不是非常有用,甚至在計算中不太常見,並且很容易模擬(只是相同字符的concat n次)。此外,人們可能對該角色應該是什麼有着截然不同的意見。

相關問題