2012-03-22 7 views
2

私はドキュメントを見て、Cソースを覗いてみましたが、なぜ彼らは受け入れられた基数を2.36に制限したのか分かりません。誰か知ってる?RubyのFixNum#to_sメソッドが2から36までの基数だけを受け入れるのはなぜですか?

+1

@muistooshortベース1が存在するが、これまでの集計リストをしましたか?あるいは、テストランナーの中には、成功したテストのために生産したドットを数えますか?その点に関しては、おそらくベースの '1/2'とさらに狂ったもの(ベース' phi'誰?)があります。 – delnan

答えて

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の基数制限の理由だと確信しています。優秀なモジュールとサンプルの使用法について、受け入れられた答え。ありがとうございました! –

+1

どうすれば '' eJA "'を '123456'に戻すことができますか? – Zac

+1

@zacそれはカスタムアルファベットのatoiです。アキュムレータをベース(アルファベットサイズ)で乗算し、文字を数値に変換してアキュムレータに加算します。 – dbenhur

2

私はルビーについて何も知らないが、私は10桁の数字と26のアルファベットがあることを知っている。それは36です。

+0

それは確かに理由があるかもしれませんが、大文字と小文字を区別すると46文字の英数字があります。これは実際には、46文字のセットのランダムな31文字の文字列を生成したいと思っていたので、 '31xinject( ''){| i | i << rand(46).to_s(46)} 'は動作しません。 –

+1

@sidewaysmilkしかし、16進数はほとんど普遍的に大文字と小文字を区別しません。上位の塩基を変更すると、ひどく矛盾します。 – delnan

+0

代わりにbase-64エンコーディングを使うことをお勧めします。 – BlueMonkMN

1

どのようにしてベース1に数値をレンダリングしますか?どのようにしてベース37の番号をレンダリングしますか?ベース300?

16進数は0..9とA..Fを使用するのが一般的です。アルファベットを高級拠点に引き続き使用するのは直感的ですが、それは36才にしかならないのです。高級拠点はほとんど見当たらないので、それ以上の慣習はありません。多分異なる獣である基盤64を除いて、おそらく1つの基盤に特有であり、ひどく古いものでもない。また、私の要点だけが強化されている、互換性のない変形があります。

ベース1の場合:単項カウントが存在しますが、計算にはそれほど有用ではなく、あまり一般的ではなく、エミュレートするのが非常に簡単です(同じ文字のconcat n)。その上、人々はおそらくそのキャラクターが何であるべきかについて、大きく異なる意見を持っているでしょう。

関連する問題