Base62 とは?
Base62 は、どこに貼り付けられても生き延びる文字だけ、つまり 10 個の数字、26 個の大文字、26 個の小文字だけで数を書く方法です。句読点も空白もパディング文字もなく、URL、ファイル名、Cookie、データベースキーに入る前にエスケープしなければならないものが何もありません。10 + 26 + 26 = 62、それが名前の由来です。
30 秒版:数 12345 は 3D7 と書かれ、1234567890 は 1LY7VK と書かれます。逆方向は同じ操作の反対で、コードを生んだ正確なアルファベットが必要です — 別のアルファベットは、エラーメッセージなしに、同じ 6 文字を別の数に戻します。
このページは 2 つの関連する仕事をします。その違いは、このページの他の何よりも重要です:
- 整数モードは入力を数として扱います。
1234567890 のような 10 進 ID は 1LY7VK になり、入力の先頭のゼロは値の一部でないため戻ってきません。
- バイトモードは入力をバイト列として扱います。バイトは 1 つの巨大なビッグエンディアン整数として読まれ、62 で割られます。同じ算術が別の量に対して走るだけです。ここでは先頭のゼロバイトの数は生き延び、ゼロバイト 1 個につきゼロ文字 1 個になります。
62 の由来と、その代償
62 は 2 のべき乗ではなく、この単一の事実が他のすべてを形作ります。おなじみのエンコーディングは入力を固定ビット群にスライスして構築されます:4 ビットが hex 文字 1 個、6 ビットが Base64 文字 1 個、5 ビットが Base32 文字 1 個。Base62 にはそれができません。62 個の値を持つ文字に収まるビット数が整数で存在しないからです — 5 ビットは 32 個の値しか名指せず、6 ビットは 64 個。だから Base62 は算術を経由します:入力全体を 1 つの整数として読み、62進で出力します。
1 文字は log2(62) = 5.954 ビットを運び、Base64 の 6 に非常に近く、10 進モードでは 1 文字が log62(10) = 1.792 桁の 10 進数字を置き換えます。長さを選ぶ前に知っておく価値がある帰結:
| コード長 | 名指せる値の数 | 実務では |
| 4 文字 | 624 = 14,776,336 | 8 桁に届かないカウンタには十分で、電話番号 1 通分の幅に収まります。 |
| 6 文字 | 626 = 56,800,235,584 | ID コードの定番の形。10 桁の 10 進 ID が 6 文字に収まります。 |
| 7 文字 | 627 = 3,521,614,606,208 | 32 ビットカウンタの範囲を 2 桁分超え、短縮リンクのスラグの幅です。 |
| 11 文字 | 6211 = 52,036,560,683,837,093,888 | 264 = 18,446,744,073,709,551,616 を超えるため、完全な 64 ビット数が 11 文字に収まります。 |
逆方向では、10 進 1,000 桁は約 558 文字、4,096 桁は 2,285 文字必要です。節約は現実的ですが有限です:Base62 は 10 進数を約 44% 短くし、最も密な印字可能エンコーディングには決して勝てません。1 文字あたり 5.954 ビットは、単純に 6.4 や 6.5 より少ないからです。
整数モード:先頭のゼロはどうなるか
整数には正準な書かれた形が 1 つだけで、それはアルファベットのゼロ文字で始まります。2 つの数字優先の順序では 0、letters-first では A です。最初の有効文字の左側はすべてパディングで、パディングは値の一部ではありません:00012345 も 12345 も 3D7 になります。固定幅が欲しいとき — 例えば列に揃えたい 7 文字コード — は、ページの固定幅にパディングボックスが幅に達するまでゼロ文字を繰り返すため、幅 7 の 12345 は数字優先アルファベットで 00003D7、letters-first で AAAADNH と印字されます。パディングは見た目です:先頭の文字は値に何も加えず、どちらの文字列をデコードしても 12345 が戻ります。0 × 626 も 0 × 625 も、どの文字がゼロを綴ってもゼロだからです。
したがってパディングされた文字列のデコードも機能し、ページは先頭の文字のうち何個がゼロ文字だったかを報告するため、「コードは 7 文字」と「値には 3 文字必要」の違いが謎のままになることはありません。
バイトモード:バイト列に対する同じ算術
バイトモードは入力バイトを 1 つのビッグエンディアン整数として読み — バイト列全体が、どんなに長くても、単一の数として扱われ — その数を 62 進で出力します。バイトは 8 ビットを含み、文字はそのうち 5.954 を名指すため、バイトモードは圧縮ではありません:入力サイズの約 134% を必要とし、Base64 の 133% よりわずかに悪いです。上のサイズ表で使った 92 バイトのサンプルでは、92 バイトは 124 の Base62 文字で出力され、Base64 も 124 文字です(その = パディングの前は 123)。Base62 は密度で Base64 に負け、文字の安全性で勝ちます。それがすべての短縮リンクと招待コードが意図的に行うトレードです。
先頭のゼロバイトは保存され、これは両方向で間違えやすい箇所です。2 つの先頭ゼロバイトに 0x01 が続くものは、数字優先アルファベットで 001、letters-first で AAB と出力されます。先頭文字がゼロを綴り、ゼロバイト 1 個につき 1 文字だからです。単一の 0x00 のバイト列は単一文字 0 として、単一の 0x01 は 1 として出力されます。これが、同じアルゴリズムを走らせながらバイトモードと整数モードの見た目が異なる唯一の場所です。
この代償として、バイトモードは算術の 2 乗時間を継承します:1,024 バイトは約 0.33 秒、2,048 バイトは約 1.3 秒と推定され、上の制限表と同じ数字です。だからバイトモードは出力 2,048 バイト、入力 2,048 文字で上限が切ってあります — 2,048 バイトは約 2,751 文字で出力されるため、このページでラウンドトリップを生き延びる最大のペイロードは約 1,520 バイトです — そして、このページのバイトモードは小さな値のリファレンスであって、本物のファイルに対するBase64 エンコード/デコード や Base91 エンコード/デコード の代替ではありません。
3 つのアルファベット、そしてアルファベットこそすべて
アルファベットの文字は固定された順序で、文字の値はその順序内の位置です。順序を動かすことは、すべての文字の意味を変えることです。3 つの順序が広く使われており、同じ数がそれぞれで 3 つの書き方を持ちます:
| 10 進 | 0-9、A-Z、a-z | 0-9、a-z、A-Z | A-Z a-z、0-9 |
| 0 | 0 | 0 | A |
| 61 | z | Z | 9 |
| 62 | 10 | 10 | BA |
| 12,345 | 3D7 | 3d7 | DNH |
| 1,234,567,890 | 1LY7VK | 1ly7vk | BViHfU |
最後の 3 列を 1 つのアルファベットとして読めば単一の首尾一貫した方式です。交換可能として読むと崩壊します。デコードは最悪の形でアルファベット盲だからです:入力のすべての文字は 3 つのアルファベットすべてに含まれるため、間違ったアルファベットはエラーを一切出さず、別の数を返すだけです。
| あるコード | 0-9 A-Z a-z として読む | 0-9 a-z A-Z として読む | A-Z a-z 0-9 として読む |
| 3D7 | 12,345 | 13,957 | 211,665 |
| 1LY7VK | 1,234,567,890 | 1,624,950,792 | 48,723,527,772 |
大文字小文字は同じ罠のより鋭い第二版です。Base62 はすべての順序で大文字小文字を区別するため、コードの小文字化は黙って書き換えます:1LY7VK は数字優先アルファベットで 1,234,567,890 ですが、1ly7vk は同じアルファベットで 1,624,950,792 です — そして偶然にも、digits-then-lower-case アルファベットでは 1,234,567,890 です。その順序がまさに、数字優先の 2 つの文字ケースを交換したものだからです。ゼロ文字も共有されません:2 つの数字優先の順序はゼロを 0 と書き、letters-first は A と書くため、そのアルファベットは数字で始まりすらしません。
他のエンコーディングと並べた Base62
| エンコーディング | 1 文字あたりビット | 入力に対するサイズ | 備考 |
| Base16(hex) | 4 | 200% | バイトあたり 2 文字、正確で簡単に読め、調べるアルファベットも不要。 |
| Base32 | 5 | 160% | 大文字小文字を区別せず口述にも安全ですが、この群では最も無駄が多い。 |
| Base36(0-9 a-z) | 約 5.17 | 約 155% | 数字と小文字のみのため、小文字化パイプラインを生き延びます。12345 は 9ix。 |
| Base58 | 約 5.86 | 約 137% | 密度ではなくアドレス用に選ばれました:紛らわしい 4 文字が、順序付けされる代わりに除外されます。Base32 / Base58 コンバーター を参照。 |
| Base62 | 約 5.95 | 約 134% | すべての文字が数字か英字のため、決してエスケープされません。密度は Base58 と Base64 の間。 |
| Base64 | 6 | 133% | どこでも既定ですが、+、/、= というエスケープを強いる 3 文字を代償にします。Base64 コンバーターを参照。 |
| Ascii85 / Base85 | 6.4 | 125% | 4 バイトを 5 文字にしますが 85 で割り、そのアルファベットは引用が必要です。Ascii85 コンバーター を参照。 |
| Base91 | 約 6.5 | 約 123% | この群で最も密ですが、出力はエスケープなしで貼るには最も安全でないものです。Base91 エンコード/デコード を参照。 |
パーセントは漸近コストを丸めたものです。実際の 92 バイト入力の実測文字数は、このページの上の方のサイズ表にあります。整数モードでは比較が逆方向に走ります。入力がバイトではなく 10 進テキストだからです:そこでは Base62 は置き換える数字より約 44% 短く、Base36 は約 36% 短い。だから ID コードは通常 Base62 か Base36 で、Base58 ではありません。
Base62 が「ではない」もの
- 標準ではない。RFC も仕様もありません。どの標準化団体も Base62 を定義したことがなく、だからこそアルファベットは保証されず、このページは 1 つに黙って決める代わりに 3 つの順序すべてを印字します。
- 暗号化ではない。基数の変更にすぎません。アルファベットを知る人は 1 パスで逆変換でき、鍵もソルトも秘密性も一切ありません。
- 圧縮ではない。バイトモードはデータを約 3 分の 1 膨らませます。整数モードが圧縮に見えるのは、10 進テキストがそもそも数を書く非効率な方法だからです。
- 大文字小文字を区別しない、ではない。Base32 は小文字化して読み戻せますが、Base62 はできません。大文字小文字を正規化するシステムを通ったコードは、破損したコードです。
- 自己検査しない。チェックサムも検査文字もないため、1 文字の誤りが、別の値の有効に見える結果を与えます。それが問題なら、Bitcoin の順序にはチェックサムが付いています — Base32 / Base58 コンバーター の Base58Check の節を参照。
- 固定長ではない。文字数は値と共に増えるため、1 から始まって 627 に達するカウンタは 1 文字から 8 文字に変わります。安定した列が必要なら固定幅にパディングしてください。
実際に噛みつく罠
- アルファベットは 10 の謎のうち 9 の答え。別のツールが同じ数で別のコードを返すなら、バグを疑う前に 2 つのアルファベットを文字ごとに比較してください。上の表は同じ値を 3 つのアルファベットで示し、3 つすべて正しいです。
- 間違ったアルファベットは黙って失敗する。そのためのエラーパスがありません:
3D7 は、どの順序を仮定するかだけで 12,345、13,957、211,665 にデコードされます。最初の文字(ゼロパディングである可能性が最も高い)と、アルファベットの先頭が数字か英字かを確認してください。
- 先頭のゼロは 2 つの意味を持つ。整数モードでは
00012345 と 12345 は同じ数で同一に印字されます。バイトモードでは先頭のゼロバイトはデータで、ゼロ文字 1 文字余分に印字されます。その文字を 1 個落とすとバイト列が変わります。
- 大文字小文字の正規化はコードを破壊する。メールアドレス、ホスト名、Windows のパスは輸送中に小文字化されることがあります。Base62 コードはそれを生き延びられず、それが Base36 が今も存在する理由です。
- 長い入力は大きいだけでなく遅い。変換は入力全体への一括算術なので、入力長を倍にすると時間が 4 倍になります。このページはハングする代わりに実測上限を超える入力を拒否します。実測値は上のサイズ表にあります。
- Base62 文字列は何の証明でもない。数字と英字のほぼ任意の文字列が文句なくデコードされるため、任意の URL スラグも何らかの数にデコードされます。コードが意味を持つのは、発行したシステムがマッピングも保存している場合だけです。
クイック回答
「同じ数なのに、別の Base62 ツールと違うコードになるのはなぜ?」
アルファベットが異なるからです。Base62 には意見の割れる仕様がなく、実装が順序を選びます:数字・大文字優先、数字・小文字優先、英字優先。このページの上部のアルファベット選択を切り替えると、3 つの答えが並んで見えます。
「Base62 は URL で安全ですか?」
はい、3 つの順序すべてで。62 文字すべてがエスケープ不要な英数字なので、クエリ文字列でパーセント三つ組に展開されるものも、URL、パスセグメント、HTML 属性を終わらせるものもありません。それが短縮リンクが Base64 ではなく Base62 である全理由です。
「Base62 と Base64 はどちらが小さい?」
バイトでは Base64 がごくわずかに小さいです:入力の約 133% 対約 134%。上の 92 バイトのサンプルでは 2 つは 124 文字で引き分けです。10 進数では Base62 がテキストを約 44% 短くし、実用的な利得はそこにあります。
「このページで Base64 文字列をデコードできますか?」
いいえ、しかも失敗したことを告げません。2 つのアルファベットは 62 文字すべてで重なるため、Base64 文字列はたいていここでも「有効」な入力で、単に別の数にデコードされます。Base64 には Base64 を使ってください。
「Base62 コードに最大長はありますか?」
理論上は上限がありません。実務上このページは 10 進 4,096 桁、2,048 バイトで止まります。背後の算術が 2 乗で、理由を説明するものを画面に何も表示できないままタブが固まるためです。実測値はこのページの上の制限表にあります。
「このページの結果が正しいとどう分かりますか?」
セルフテストを押してください。記録されたすべてのサンプル、0〜64 のすべてのバイト長、10 進数のさまざまな値を 3 つのアルファベットすべてで実行して返り値と入り値を比較し、各アルファベットの 62 文字すべてが URL で安全であることも再チェックします。サンプルボタンはさらに、3 つの結果をこのページのデータファイルに記録された値(本サイトのテストツールに保管された第二の独立した多倍長整数実装で検証済み)と比較します。
規格とクレジット
ここに実装する標準はありません:Base62 は仕様ではなく慣習で、上に印字した 3 つのアルファベットが実際のソフトウェアに現れるものです。このページは本サイト独自の多倍長整数ルーチンで実装しています。桁配列への素朴な算術で書かれており、どのサイズも JavaScript の数値型に制限されません。
ページのテキストは本サイトのために書かれました。このページのすべての worked 例はページ自身のコードで生成され、本サイトのテストツールに保管された、ネイティブ多倍長整数を使う第二の独立した実装に対して検証済みです。同じ実装がデータファイル内のサンプル表とサイズ表も検証しました。