Base 62変換


90

整数を62進数に変換するにはどうすればよいですか(16進数と同様ですが、これらの数字は '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'です)。

私はそれに適したPythonライブラリを見つけようとしましたが、それらはすべて文字列の変換に専念しているようです。Python base64モジュールは文字列のみを受け入れ、1桁を4文字に変換します。私は、URL短縮機能が使用するものに似たものを探していました。


誰かがオープンソースプロジェクトのアイデアを見つけたように
聞こえ

短いURLを作成する場合は、エンコードする必要のない文字セット全体を使用することができます:en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters。それは66文字です。
l0b0 2009

ユーザーの混乱を避けるために、ドットとティルダを渡すと思いますが、ダッシュとアンダースコアは追加する価値があります。
mikl 2009

Base64はどうですか?あなたはそのためのライブラリを見つける幸運があるかもしれません。
マイククーパー、

:この質問は適用回答数があるstackoverflow.com/questions/561486/...
マイル

回答:


166

このための標準モジュールはありませんが、それを実現するための独自の関数を記述しました。

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def encode(num, alphabet):
    """Encode a positive number into Base X and return the string.

    Arguments:
    - `num`: The number to encode
    - `alphabet`: The alphabet to use for encoding
    """
    if num == 0:
        return alphabet[0]
    arr = []
    arr_append = arr.append  # Extract bound-method for faster access.
    _divmod = divmod  # Access to locals is faster.
    base = len(alphabet)
    while num:
        num, rem = _divmod(num, base)
        arr_append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

def decode(string, alphabet=BASE62):
    """Decode a Base X encoded string into the number

    Arguments:
    - `string`: The encoded string
    - `alphabet`: The alphabet to use for decoding
    """
    base = len(alphabet)
    strlen = len(string)
    num = 0

    idx = 0
    for char in string:
        power = (strlen - (idx + 1))
        num += alphabet.index(char) * (base ** power)
        idx += 1

    return num

エンコーディングとデコーディングに使用する任意のアルファベットを指定できることに注意してください。あなたが離れる場合alphabet引数、コードの最初の行で定義されている62文字のアルファベットが取得されるため、62ベースへのエンコード/デコードが行われます。

お役に立てれば。

PS-URLの短縮については、0Ol1oIなどの混乱しやすい文字をいくつか除外する方が良いことがわかりました。このため、このアルファベットをURLの短縮のニーズに使用しています- "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

楽しんで。


5
+1:いいね!これは、URLフレンドリーな文字で拡張して、あちこちに1文字を保存することができます。私は安全である知っているキャラクターは、以下のとおりです。$-_.+!*'(),;/?:@&= あなたはおそらくあまりにものようないくつかの他の文字を使用することができます[]~など
Blixt

24
命名のバグ:アルファベットはカスタマイズ可能であるため、ベース62ではありません。
アンワインド

3
デコードの場合、累乗を計算しないほうがよい習慣です(時間を節約し、書き込み時間は短くなりますが、重要なのは1つずれたエラーを回避することです)。したがって、num = 0; 文字列内の文字の場合:num = num * base + alphabet.index(char)
ShreevatsaR

1
@ShreevatsaR:辞書検索の代わりにstr.index()を使用する特定の理由は?私の答えを見てください...
ジョン・マチン

2
ジョナサン-Pythonは任意の長さの数値を処理できます-オーバーフローはありません:>>> 256 *(62 ** 100)44402652562862911414971048359760030835982580330786570771137804709455598239929932673552190201125730101070867075377228748911717860448985185350731601887476350502973424822800696272224256s
Anthony

53

私もこれを行うためのスクリプトを書いたことがありますが、とてもエレガントだと思います:)

import string
# Remove the `_@` below for base62, now it has 64 characters
BASE_LIST = string.digits + string.letters + '_@'
BASE_DICT = dict((c, i) for i, c in enumerate(BASE_LIST))

def base_decode(string, reverse_base=BASE_DICT):
    length = len(reverse_base)
    ret = 0
    for i, c in enumerate(string[::-1]):
        ret += (length ** i) * reverse_base[c]

    return ret

def base_encode(integer, base=BASE_LIST):
    if integer == 0:
        return base[0]

    length = len(base)
    ret = ''
    while integer != 0:
        ret = base[integer % length] + ret
        integer /= length

    return ret

使用例:

for i in range(100):                                    
    print i, base_decode(base_encode(i)), base_encode(i)

9
このバージョンは、バイシャンパヤンから受け入れられているソリューションよりもかなり高速です。関数の外で長さを計算することにより、さらに最適化しました。テスト結果(100,000反復):version-WoLpH:.403 .399 .399 .398 .398 | バージョン-Baishampayan:1.783 1.785 1.782 1.788 1.784。このバージョンは約4倍高速です。
ジョーダン

base_decode関数でreversed(string)スライスするよりも高速に使用する場合string[::-1]
遠藤孝直2014年

1
この質問を見つけるのに長い時間がかかりました。これがbase62変換と呼ばれることを知らなかった。素敵な答え。

正しい残りを取得するために変更integer /= lengthするinteger //=length必要がありました
karlgold

10

次のデコーダーメーカーは、妥当なベースで動作し、より整然としたループを備えており、無効な文字に遭遇すると明示的なエラーメッセージを表示します。

def base_n_decoder(alphabet):
    """Return a decoder for a base-n encoded string
    Argument:
    - `alphabet`: The alphabet used for encoding
    """
    base = len(alphabet)
    char_value = dict(((c, v) for v, c in enumerate(alphabet)))
    def f(string):
        num = 0
        try:
            for char in string:
                num = num * base + char_value[char]
        except KeyError:
            raise ValueError('Unexpected character %r' % char)
        return num
    return f

if __name__ == "__main__":
    func = base_n_decoder('0123456789abcdef')
    for test in ('0', 'f', '2020', 'ffff', 'abqdef'):
        print test
        print func(test)

私はおそらくこれを使用することはないでしょうが、私はあなたに創造性のために親指を上げすぎました。このコードは私を笑わせました。:)
Sepero 2013年

@セペロ:何がそんなに面白いの?これは、真面目で堅牢な産業用ソフトウェアです。**ループ内で演算子を使用して逆転するミッキーマウスはありません。
John Machin 2013年

友達を落ち着かせて。あなたが正しい。質問に関係のないもの(ラッピング、エラーチェック、単体テスト)に埋め込まれているため、内部ループの真の良さを逃しました。
Sepero、2013年

見た目は良いですが、文字列を生成するために整数とアルファベットを使用する「産業用強度」のエンコーダを忘れていませんか?
martineau 2013年

1
最後の値のqは、発生したValueErrorを自慢するためのものですか?
Thomas Vander Stichele 2014

7

最高の効率(djangoなど)を探している場合は、次のようなものが必要になります。このコードは、Baishampayan GhoseとWoLpH、およびJohn Machinの効率的なメソッドの組み合わせです。

# Edit this list of characters as desired.
BASE_ALPH = tuple("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_ALPH))
BASE_LEN = len(BASE_ALPH)

def base_decode(string):
    num = 0
    for char in string:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def base_encode(num):
    if not num:
        return BASE_ALPH[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding = BASE_ALPH[rem] + encoding
    return encoding

事前に辞書を計算しておくこともできます。(注:文字列を使用したエンコードは、非常に長い数値であっても、リストを使用した場合よりも効率的です。)

>>> timeit.timeit("for i in xrange(1000000): base.base_decode(base.base_encode(i))", setup="import base", number=1)
2.3302059173583984

2.5秒未満で100万の数値をエンコードおよびデコードしました。(2.2 GHz i7-2670QM)


初めは必ずしもtuple()周りBASE_ALPHを必要としない。Pythonでは、すべての文字列は反復可能です。もちろん、この機能はによって利用されていenumerate()ます。したがって、コードはさらにスリムになります:)
Luis Nell

6
origiNellさん、tuple()が不要なのは正しいですが、私のシステムでは、コードの実行が約20%速くなっています。tuple()なしでテストしてみて、何が最適かを確認してください。乾杯:)
Sepero 2013

興味深い点。タプルは文字列よりも軽量なので、理にかなっています。啓蒙をありがとう:)!
Luis Nell

@Sepero私はさらに、フォーマット、命名、テスト、機能性(負の数がサポートされている)の面でバージョンを改善:pastebin.com/4uket7iuを(あなたはこれであなたの答えを更新する場合があります)
Joschua

@Joschua-URLのコードが機能しませんでした。base_encode()は、テストした数値に対して1つのエンコードされた数字のみを生成するように見えました。
SMGreenfield

4

djangoフレームワークを使用する場合は、django.utils.baseconvモジュールを使用できます。

>>> from django.utils import baseconv
>>> baseconv.base62.encode(1234567890)
1LY7VK

base62に加えて、baseconvはbase2 / base16 / base36 / base56 / base64も定義しました。


3

おそらくbase62ではなく、base64が必要です。URLと互換性のあるバージョンが存在するため、余分な2つのフィラー文字は問題になりません。

プロセスはかなり単純です。base64が6ビットを表し、通常のバイトが8を表すと考えてください。選択した64文字のそれぞれに000000〜111111の値を割り当て、4つの値をまとめて3つのbase256バイトのセットと一致させます。3バイトのセットごとに繰り返し、最後に任意のパディング文字をパディングします(通常は0が便利です)。


5
標準のPython base64エンコード方式は、バイト(つまり文字列/文字)のエンコード用に最適化されているため、短いURLには実際には適しておらず、数値をベースシフトするよりも長い出力を生成します。
mikl

@miklもちろん、Pythonのbase64モジュールは短いURLの生成には適していない可能性がありますが、Pythonのすべてのエンコーディングメソッドは実際にはbase-256の数値シーケンスで機能しています。バイトは実際にはbase-256でエンコードされた「文字列」です。Python 2.xは文字列をバイトのシーケンスとして扱いますが、Python 3.x(これは正しいことを行います)は文字列をUnicodeとして扱います。したがって、b'foobar 'は、[102、111、111、98、97、114]または[0x66,0x6f、0x6f、0x62,0x61,0x72]またはb' \ x66 \ x6f \ x6f \ x62 \ x61 \ x72 'は、当然のことながらbase-256表現です。バイトは文字列や文字ではありません。バイトはバイトです。=)
yesudeep

@yesudeep:それで、バイトはバイトです...そしてあなたのポイントは正確には何ですか?
martineau 2013年

3

必要なのは、何かをエンコード/デコードするのではなく、短いIDを生成することだけである場合(URLの短縮形について言及しているため)、このモジュールが役立つ可能性があります。

https://github.com/stochastic-technologies/shortuuid/


これが短いURLに適しているかどうかはわかりません。UUIDは通常非常に大きな数値であるため、base57のようにエンコードしたとしても、短いURLの場合はかなり長くなります。
mikl

あなたは好きなだけカットすることができます、それは純粋にランダムなので衝突はまだ起こりそうにありませんが、もはやユニークなIDにはなりません。
Stavros Korokithakis

2

あなたはpybaseからzbase62モジュールをダウンロードできます

例えば

>>> import zbase62
>>> zbase62.b2a("abcd")
'1mZPsa'

2
ええ、以前に見ましたが、数値ではなく文字列を変換します:)
mikl

2

私は他の人の投稿から大きな恩恵を受けています。私はもともとDjangoプロジェクト用のpythonコードを必要としていましたが、それ以来node.jsを使用するようになったので、ここにBaishampayan Ghoseが提供したコード(エンコード部分)のJavaScriptバージョンを示します。

var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

function base62_encode(n, alpha) {
  var num = n || 0;
  var alphabet = alpha || ALPHABET;

  if (num == 0) return alphabet[0];
  var arr = [];
  var base = alphabet.length;

  while(num) {
    rem = num % base;
    num = (num - rem)/base;
    arr.push(alphabet.substring(rem,rem+1));
  }

  return arr.reverse().join('');
}

console.log(base62_encode(2390687438976, "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"));

私はこのコードを更新し、github.com / sbussard / encode
Stephen

2

次のスニペットが役立つことを願っています。

def num2sym(num, sym, join_symbol=''):
    if num == 0:
        return sym[0]
    if num < 0 or type(num) not in (int, long):
        raise ValueError('num must be positive integer')

    l = len(sym)  # target number base
    r = []
    div = num
    while div != 0: # base conversion
        div, mod = divmod(div, l)
        r.append(sym[mod])

    return join_symbol.join([x for x in reversed(r)])

あなたのケースの使い方:

number = 367891
alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
print num2sym(number, alphabet)  # will print '1xHJ'

明らかに、より少ないまたはより多い数の記号で構成される別のアルファベットを指定することができます、そしてそれはより少ないまたはより大きな数の基数にあなたの数を変換します。たとえば、アルファベットとして「01」を指定すると、入力番号をバイナリとして表す文字列が出力されます。

最初にアルファベットをシャッフルして、数字を独自に表現することができます。URL短縮サービスを作成している場合に役立ちます。


1
悪くない。使用したいかもしれませんif num < 0 or type(num) not in (int, long):
martineau 2013年

これはより良い方法ですがlong、Py 3.xには存在しないため、少し複雑になります。そのため、この回答を使用することをお勧めします。
martineau 2013年

1
または、独自のポータブルバージョンを使用しますisinstance(x, (type(1), type(2**32)))
martineau 2013年

2

これのためのpythonライブラリができました。

このためのpipパッケージの作成に取り組んでいます。

bases.js に触発された私のbases.py https://github.com/kamijoutouma/bases.pyを使用することをお勧めします

from bases import Bases
bases = Bases()

bases.toBase16(200)                // => 'c8'
bases.toBase(200, 16)              // => 'c8'
bases.toBase62(99999)              // => 'q0T'
bases.toBase(200, 62)              // => 'q0T'
bases.toAlphabet(300, 'aAbBcC')    // => 'Abba'

bases.fromBase16('c8')               // => 200
bases.fromBase('c8', 16)             // => 200
bases.fromBase62('q0T')              // => 99999
bases.fromBase('q0T', 62)            // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300

使用できるベースについては、https://github.com/kamijoutouma/bases.py#known-basesalphabetsを参照してください


2

これが私の解決策です:

def base62(a):
    baseit = (lambda a=a, b=62: (not a) and '0' or
        baseit(a-a%b, b*62) + '0123456789abcdefghijklmnopqrstuvwxyz'
                              'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[a%b%61 or -1*bool(a%b)])
    return baseit()

説明

どのベースでも、すべての数値はに等しい a1+a2*base**2+a3*base**3...ので、すべてのを見つけることが目標ですa

すべてのためのN=1,2,3...コードを分離aN*base**Nすることによって、「moduloing」によってbためb=base**(N+1)れるすべてのスライスaよりも大きいだN、すべてのスライスaそのシリアルよりも小さくなるようにsのN減少によってa機能が電流によって再帰的に呼び出されるたびにaN*base**N

Base%(base-1)==1したがってbase**p%(base-1)==1、したがってq*base^p%(base-1)==q1つだけ例外があり、q==base-1が返されます0。そのケースを修正するためにそれは戻ります0。関数0は最初からチェックします。


利点

このサンプルでは、​​乗算(除算の代わりに)が1つと、いくつかのモジュラス演算があり、これらはすべて比較的高速です。


1

個人的に、私はBaishampayanのソリューションを気に入っています。これは、主に混乱しているキャラクターを取り除くためです。

完全性と、より良いパフォーマンスのソリューションのために、この投稿ではPython base64モジュールを使用する方法を示しています。


1
Williham Totlandへの私のコメントで述べたように、Pythons base64は文字列用に最適化されているため、数値のエンコードに最適ではありません。
mikl

1

私はしばらく前にこれを書きました、そしてそれはかなりうまくいきました(ネガティブとすべてが含まれています)

def code(number,base):
    try:
        int(number),int(base)
    except ValueError:
        raise ValueError('code(number,base): number and base must be in base10')
    else:
        number,base = int(number),int(base)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = [0,1,2,3,4,5,6,7,8,9,"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"]
    final = ""
    loc = 0
    if number < 0:
        final = "-"
        number = abs(number)
    while base**loc <= number:
        loc = loc + 1
    for x in range(loc-1,-1,-1):
        for y in range(base-1,-1,-1):
            if y*(base**x) <= number:
                final = "{}{}".format(final,numbers[y])
                number = number - y*(base**x)
                break
    return final

def decode(number,base):
    try:
        int(base)
    except ValueError:
        raise ValueError('decode(value,base): base must be in base10')
    else:
        base = int(base)
    number = str(number)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = ["0","1","2","3","4","5","6","7","8","9","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"]
    final = 0
    if number.startswith("-"):
        neg = True
        number = list(number)
        del(number[0])
        temp = number
        number = ""
        for x in temp:
            number = "{}{}".format(number,x)
    else:
        neg = False
    loc = len(number)-1
    number = str(number)
    for x in number:
        if numbers.index(x) > base:
            raise ValueError('{} is out of base{} range'.format(x,str(base)))
        final = final+(numbers.index(x)*(base**loc))
        loc = loc - 1
    if neg:
        return -final
    else:
        return final

すべての長さについて申し訳ありません


1
BASE_LIST = tuple("23456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_LIST))
BASE_LEN = len(BASE_LIST)

def nice_decode(str):
    num = 0
    for char in str[::-1]:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def nice_encode(num):
    if not num:
        return BASE_LIST[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding += BASE_LIST[rem]
    return encoding

1
これは、BASE_LISTの名前を修正し、Speroのその他の優れた回答で省略されていたデコード時の文字列を逆にします
paulkav1

1

これを行うには、再帰的で反復的な方法があります。反復回数は、実行回数に応じて少し速くなります。

def base62_encode_r(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return s[dec] if dec < 62 else base62_encode_r(dec / 62) + s[dec % 62]
print base62_encode_r(2347878234)

def base62_encode_i(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = ''
    while dec > 0:
        ret = s[dec % 62] + ret
        dec /= 62
    return ret
print base62_encode_i(2347878234)

def base62_decode_r(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if len(b62) == 1:
        return s.index(b62)
    x = base62_decode_r(b62[:-1]) * 62 + s.index(b62[-1:]) % 62
    return x
print base62_decode_r("2yTsnM")

def base62_decode_i(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = 0
    for i in xrange(len(b62)-1,-1,-1):
        ret = ret + s.index(b62[i]) * (62**(len(b62)-i-1))
    return ret
print base62_decode_i("2yTsnM")

if __name__ == '__main__':
    import timeit
    print(timeit.timeit(stmt="base62_encode_r(2347878234)", setup="from __main__ import base62_encode_r", number=100000))
    print(timeit.timeit(stmt="base62_encode_i(2347878234)", setup="from __main__ import base62_encode_i", number=100000))
    print(timeit.timeit(stmt="base62_decode_r('2yTsnM')", setup="from __main__ import base62_decode_r", number=100000))
    print(timeit.timeit(stmt="base62_decode_i('2yTsnM')", setup="from __main__ import base62_decode_i", number=100000))

0.270266867033
0.260915645986
0.344734796766
0.311662500262

私はあなたの再帰的なアプローチが本当に好きでした。AP Comp Sciを取っていた私の娘は、C '++で「base25」(「ABCDEFHJKMNPQRTUVWXY34789」を使用)を実装するために、これと同じソリューションを見つけました。私はそれをPythonに変換し、その言語でまったくの新人になり、いくつかの障害にぶつかりました。1行のコードでエレガントに解決しました!0から9で始まらないアルファベットの空の文字列への0の変換という一般的な問題も回避できます。すごい仕事!(私は負の数は必要ありませんが、あなたのアプローチはとても良かったので、将来のブラウザのためにそれを追加するのは良いかもしれません)
SMGreenfield '26

1

パイソン 3.7.x

既存のbase62スクリプトを探しているときに、いくつかのアルゴリズムのPhDのgithubを見つけました。現時点では、Python 3の現在の最大バージョンでは機能しなかったため、必要に応じて修正し、少しリファクタリングを行いました。私は通常はPythonを使用せず、常にアドホックで使用しているので、YMMVです。すべてのクレジットは、Zhihua Lai博士に帰属します。このバージョンのPythonの問題を解決しました。

ファイル base62.py

#modified from Dr. Zhihua Lai's original on GitHub
from math import floor
base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
b = 62;
def toBase10(b62: str) -> int:
    limit = len(b62)
    res = 0
    for i in range(limit):
        res = b * res + base.find(b62[i])
    return res
def toBase62(b10: int) -> str:
    if b <= 0 or b > 62:
        return 0
    r = b10 % b
    res = base[r];
    q = floor(b10 / b)
    while q:
        r = q % b
        q = floor(q / b)
        res = base[int(r)] + res
    return res

ファイル try_base62.py

import base62
print("Base10 ==> Base62")
for i in range(999):
    print(f'{i} => {base62.toBase62(i)}')
base62_samples = ["gud", "GA", "mE", "lo", "lz", "OMFGWTFLMFAOENCODING"]
print("Base62 ==> Base10")
for i in range(len(base62_samples)):
    print(f'{base62_samples[i]} => {base62.toBase10(base62_samples[i])}')

の出力 try_base62.py

Base10 ==> Base62
0 => 0
[...]
998 => g6
Base62 ==> Base10
gud => 63377
GA => 2640
mE => 1404
lo => 1326
lz => 1337
OMFGWTFLMFAOENCODING => 577002768656147353068189971419611424

リポジトリにライセンス情報がなかったので、私はPRを提出しました。そのため、元の作者は少なくとも他の人がコードを使用および変更していることを知っています。


0

ライブラリのお手伝いはできません。私はbase64を使用して、選択に余分な文字を追加することを好みます-可能であれば!

その後、base64モジュールを使用できます。

これが本当に、実際には不可能である場合:

この方法で自分で行うことができます(これは疑似コードです):

base62vals = []
myBase = 62
while num > 0:
   reminder = num % myBase
   num = num / myBase
   base62vals.insert(0, reminder)

0

単純な再帰で

"""
This module contains functions to transform a number to string and vice-versa
"""
BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
LEN_BASE = len(BASE)


def encode(num):
    """
    This function encodes the given number into alpha numeric string
    """

    if num < LEN_BASE:
        return BASE[num]

    return BASE[num % LEN_BASE] + encode(num//LEN_BASE)


def decode_recursive(string, index):
    """
    recursive util function for decode
    """

    if not string or index >= len(string):
        return 0

    return (BASE.index(string[index]) * LEN_BASE ** index) + decode_recursive(string, index + 1)


def decode(string):
    """
    This function decodes given string to number
    """

    return decode_recursive(string, 0)

0

これまでで最もシンプル。

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def encode_base62(num):
    s = ""
    while num>0:
      num,r = divmod(num,62)
      s = BASE62[r]+s
    return s


def decode_base62(num):
   x,s = 1,0
   for i in range(len(num)-1,-1,-1):
      s = int(BASE62.index(num[i])) *x + s
      x*=62
   return s

print(encode_base62(123))
print(decode_base62("1Z"))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.