Base36 変換ツールの使い方
- 入力 · テキストにテキストを入力します。その UTF-8 のバイト列がエンコードされ、結果が出力 · Base36 に表示されます。
- 出力の下の大文字/小文字で小文字か大文字を選びます。どちらも同じようにデコードできます。
- 数を変換するには、変換元を整数(多倍長)にして 10進数の値を入力します。変換先を変更していた場合は Base36 に戻します。
- デコードするには、方向の切り替えで Base36 → テキストをクリックするか、10進数が欲しければ変換先を整数(多倍長)にします。
Base36 と 10進数の相互変換
Base36 は 0–9 の後に a–z で数えるので、a は 10、z は 35 です。各桁は右隣の桁の 36 倍の重みを持ちます。
| Base36 | 10進数 | 備考 |
|---|---|---|
z | 35 | 1 桁で最大の値 |
10 | 36 | |
zz | 1295 | 35 × 36 + 35 |
1000 | 46656 | 36³ |
21i3v9 | 123456789 | |
2gosa7pa2gv | 9007199254740991 | JavaScript の Number.MAX_SAFE_INTEGER |
3w5e11264sgsf | 18446744073709551615 | 2^64 − 1 |
変換ツールは BigInt で計算するので、64 ビットや 128 ビットの値も正確に出力されます。上限は入力 64 KB で、どんな ID よりもはるかに大きな値です。
Base36 が使われる場所
Base36 は、短くしたい識別子で、しかも大文字小文字を変えてしまうシステムを通り抜けなければならないものに向いています。一部のソフトウェアが小文字にしてしまう URL、大文字小文字を区別しないファイルシステム、読み上げたり紙から入力したりするコードなどです。Reddit の投稿やコメントの ID がその一例です。また、ほとんどのプログラミング言語はライブラリなしで Base36 の数を読めます。
他の方式と比べると、Base36 は大文字小文字を区別しない代わりに密度を少し犠牲にしています。ランダムな 16 バイトは Base36 で 24〜25 文字、Base62 で 21〜22 文字、16進数で 32 文字です。Base62 はもっと短くなりますが大文字小文字を区別し、Base32 も大文字小文字を区別しませんが、アルファベットを 5 ビットのグループに固定し、パディングを加えます。
テキスト、バイト列、先頭のゼロ
テキストやその他のバイト列の場合、変換ツールは入力をビッグエンディアンの 1 つの数として読み、その数を 36 進数で書きます。Hello はバイト列 48 65 6c 6c 6f、数としては 310939249775 で、Base36 では 3yud78mn です。純粋な数では先頭のゼロバイトが消えてしまうため、それぞれを 0 の桁として書きます。バイト列 00 0a は 0a にエンコードされます。
整数の入力では、先頭のゼロの問題は起きません。10進数には失われる先頭のゼロバイトがないからです。
JavaScript と Python での Base36
どちらの言語も数の変換を標準で備えています。
(255).toString(36); // '73'
parseInt("73", 36); // 255
(2n ** 64n - 1n).toString(36) // '3w5e11264sgsf'
BigInt は 36 進数で出力できますが、それを解析する機能はなく、parseInt は 2^53 を超えると精度を失います。短いループで解決できます。
function parseBase36(s) {
let n = 0n;
for (const ch of s.toLowerCase()) n = n * 36n + BigInt(parseInt(ch, 36));
return n;
}
parseBase36("3w5e11264sgsf"); // 18446744073709551615n
Python の int() は基数を受け取り、どんな大きさでも扱えます。int("3w5e11264sgsf", 36) は 18446744073709551615 を返します。逆方向の組み込み関数はありませんが、アルファベット 0123456789abcdefghijklmnopqrstuvwxyz を使った divmod のループで実現できます。その他のパターンは JavaScript と Python のページにあります。
よくある問題
- 値の途中の
-、_、空白の位置でエラーになる。 Base36 にあるのは数字と英字だけです。区切り文字を取り除くか、複数の ID を区切っているならそこで分割してください。 - デコードしたテキストが文字化けする。 その文字列はエンコードされたテキストではなく、おそらく数値の ID です。変換先を整数(多倍長)にして数として確認してください。
- スプレッドシートや JSON で下の桁がわずかに違う。 どこかで数が倍精度浮動小数点数を経由しています。大きな ID は最初から最後まで文字列のまま扱ってください。
よくある質問
Base36 を 10進数に変換するにはどうすればいいですか?
変換元を Base36 に、変換先を整数(多倍長)にしてから、Base36 の値を貼り付けます。zz は 1295 に、3w5e11264sgsf は符号なし 64 ビットの最大値 18446744073709551615 になります。
Base36 は大文字と小文字を区別しますか?
しません。大文字と小文字の英字は同じ値を持つので、ZZ も zz も 1295 です。そのため Base36 は、大文字小文字の変換に耐える一般的なエンコーディングの中で最も高密度です。
JavaScript の parseInt で違う数になるのはなぜですか?
parseInt(s, 36) は倍精度浮動小数点数を返し、正確なのは 2^53 までです。parseInt("3w5e11264sgsf", 36) は 18446744073709552000 を返し、385 ずれます。このページで紹介しているように、代わりに BigInt に変換してください。
Hello の Base36 が parseInt('Hello', 36) と違うのはなぜですか?
エンコーダーはテキストの 5 バイトを 1 つの数にし、それを 36 進数で書きます(3yud78mn)。一方 parseInt は H-e-l-l-o という文字を Base36 の桁として読み、29234652 を返します。