Apa itu Base62?
Base62 adalah cara menulis angka hanya dengan karakter yang aman saat ditempel di mana saja: sepuluh digit, 26 huruf besar, dan 26 huruf kecil. Tanpa tanda baca, tanpa spasi, tanpa karakter padding, tidak ada yang perlu di-escape sebelum masuk ke URL, nama file, cookie, atau kunci basis data. Sepuluh ditambah 26 ditambah 26 sama dengan 62, dan dari situlah namanya.
Versi 30 detik: angka 12345 ditulis sebagai 3D7, dan 1234567890 ditulis sebagai 1LY7VK. Arah sebaliknya adalah operasi yang sama dibalik, dan membutuhkan alfabet yang tepat yang menghasilkan kode tersebut — alfabet yang berbeda mengubah enam karakter yang sama kembali menjadi angka yang berbeda, tanpa pesan error apa pun.
Halaman ini melakukan dua pekerjaan yang saling terkait, dan perbedaan di antara keduanya lebih penting daripada hal lain di halaman ini:
- Mode integer memperlakukan input sebagai angka. ID desimal seperti
1234567890 menjadi 1LY7VK, dan angka nol di depan input bukan bagian dari nilai, sehingga tidak kembali.
- Mode byte memperlakukan input sebagai string byte. Byte dibaca sebagai satu bilangan bulat big-endian yang sangat besar lalu dibagi 62, yaitu aritmetika yang sama pada kuantitas yang berbeda. Di sini jumlah byte nol di depan tetap dipertahankan, satu byte nol untuk setiap karakter nol.
Dari mana angka 62 berasal, dan apa biayanya
62 bukan pangkat dua, dan fakta tunggal itu membentuk semua yang lain. Encoding yang sudah dikenal dibangun dengan memotong input menjadi grup bit tetap: 4 bit dicetak sebagai satu karakter heksadesimal, 6 bit sebagai satu karakter Base64, 5 bit sebagai satu karakter Base32. Base62 tidak bisa melakukan itu, karena tidak ada jumlah bit utuh yang sesuai dengan karakter bernilai 62 — 5 bit hanya menamai 32 nilai, 6 bit menamai 64. Maka Base62 memakai aritmetika: baca seluruh input sebagai satu bilangan bulat, lalu cetak dalam basis 62.
Satu karakter kemudian membawa log2(62) = 5,954 bit, yang sangat dekat dengan 6 milik Base64, dan dalam mode desimal satu karakter menggantikan log62(10) = 1,792 digit desimal. Beberapa konsekuensi yang patut diketahui sebelum memilih panjang:
| Panjang kode | Nilai yang dapat ditampung | Dalam praktik |
| 4 karakter | 624 = 14.776.336 | Cukup untuk penghitung yang tetap di bawah delapan digit, dan muat dalam ruang sebesar satu nomor telepon. |
| 6 karakter | 626 = 56.800.235.584 | Bentuk umum kode ID. ID desimal sepuluh digit muat dalam enam karakter. |
| 7 karakter | 627 = 3.521.614.606.208 | Melampaui rentang penghitung 32-bit dua orde besaran, dalam lebar slug tautan pendek. |
| 11 karakter | 6211 = 52.036.560.683.837.093.888 | Lebih besar dari 264 = 18.446.744.073.709.551.616, sehingga angka 64-bit penuh muat dalam sebelas karakter. |
Dari arah sebaliknya, 1.000 digit desimal memerlukan sekitar 558 karakter, dan 4.096 digit desimal memerlukan 2.285. Penghematannya nyata tetapi terbatas: Base62 memperpendek bilangan desimal sekitar 44%, dan tidak pernah mengalahkan encoding yang paling padat yang dapat dicetak, karena 5,954 bit per karakter memang lebih sedikit daripada 6,4 atau 6,5.
Mode integer: apa yang terjadi pada angka nol di depan
Sebuah bilangan bulat memiliki satu bentuk tertulis yang kanonik dan diawali karakter nol dari alfabet, yaitu 0 pada dua urutan angka-dulu dan A pada urutan huruf-dulu. Semua yang ada di kiri karakter bermakna pertama adalah padding, dan padding bukan bagian dari nilai: 00012345 dan 12345 keduanya menjadi 3D7. Jika diinginkan lebar tetap — misalnya kode tujuh karakter yang harus sejajar dalam kolom — kotak Beri padding hasil ke lebar tetap di halaman ini mengulang karakter nol hingga lebar tercapai, sehingga 12345 pada lebar 7 dicetak 00003D7 dalam alfabet angka-dulu dan AAAADNH dalam alfabet huruf-dulu. Padding bersifat kosmetik: karakter di depan itu tidak menambah nilai, dan mendekode salah satu string menghasilkan 12345 kembali, karena 0 × 626 dan 0 × 625 sama-sama nol apa pun karakter yang mengeja nolnya.
Dengan demikian mendekode string yang diberi padding juga berfungsi, dan halaman ini melaporkan berapa karakter di depan yang merupakan karakter nol, sehingga selisih antara "kodenya tujuh karakter" dan "nilainya hanya membutuhkan tiga karakter" tidak pernah membingungkan.
Mode byte: aritmetika yang sama pada string byte
Mode byte membaca byte input sebagai satu bilangan bulat big-endian — seluruh string byte diperlakukan sebagai satu angka, berapa pun panjangnya — lalu mencetak angka itu dalam basis 62. Karena satu byte berisi 8 bit dan satu karakter memuat 5,954 bit, mode byte bukan kompresi: ia membutuhkan sekitar 134% dari ukuran input, sedikit lebih buruk daripada 133% milik Base64. Pada sampel 92 byte yang dipakai di tabel ukuran di atas, 92 byte dicetak menjadi 124 karakter Base62, dan Base64 juga mencetak 124 (123 di antaranya sebelum padding =). Base62 kalah dari Base64 dalam kepadatan dan menang dalam keamanan karakter, dan itulah pertukaran yang sengaja dibuat setiap tautan pendek dan kode undangan.
Byte nol di depan dipertahankan, dan ini mudah keliru ke dua arah. Dua byte nol di depan diikuti 0x01 dicetak sebagai 001 dalam alfabet angka-dulu dan AAB dalam alfabet huruf-dulu, karena karakter di depan mengeja nol dan jumlahnya satu per byte nol. String byte yang hanya berisi 0x00 dicetak sebagai satu karakter 0, dan string byte yang hanya berisi 0x01 dicetak sebagai 1. Inilah satu-satunya tempat mode byte dan mode integer tampak berbeda walaupun algoritmanya sama.
Harga dari semua ini adalah mode byte mewarisi waktu kuadratik dari aritmetikanya: 1.024 byte diperkirakan sekitar sepertiga detik dan 2.048 byte sekitar 1,3 detik, sama dengan angka pada tabel batas di atas. Itulah sebabnya mode byte di sini dibatasi 2.048 byte keluar dan 2.048 karakter masuk — 2.048 byte dicetak menjadi sekitar 2.751 karakter, sehingga sekitar 1.520 byte adalah payload terbesar yang bertahan dalam round trip melalui halaman ini — dan mengapa mode byte di halaman ini adalah referensi untuk nilai kecil, bukan pengganti Base64 atau Base91 untuk file nyata.
Tiga alfabet, dan mengapa alfabet adalah seluruh cerita
Karakter dalam alfabet adalah urutan tetap, dan nilai sebuah karakter adalah posisinya dalam urutan itu. Memindahkan urutan mengubah arti setiap karakter. Ada tiga urutan yang banyak dipakai, dan ini adalah angka yang sama yang ditulis tiga cara di masing-masing:
| Desimal | 0-9 lalu A-Z lalu a-z | 0-9 lalu a-z lalu A-Z | A-Z lalu a-z lalu 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 |
Membaca ketiga kolom terakhir sebagai satu alfabet menghasilkan skema yang koheren. Membacanya sebagai dapat saling dipertukarkan membuatnya runtuh, karena dekode buta-alfabet dengan cara terburuk: setiap karakter input ada di ketiga alfabet, sehingga alfabet yang salah tidak menghasilkan error sama sekali, hanya angka yang berbeda.
| Sebuah kode | Dibaca sebagai 0-9 A-Z a-z | Dibaca sebagai 0-9 a-z A-Z | Dibaca sebagai 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 |
Huruf besar-kecil adalah versi kedua dari jebakan yang sama, lebih tajam. Base62 peka huruf besar-kecil di setiap urutan, sehingga mengubah kode menjadi huruf kecil diam-diam menulis ulang kodenya: 1LY7VK adalah 1.234.567.890 dalam alfabet angka-dulu, sedangkan 1ly7vk adalah 1.624.950.792 dalam alfabet yang sama — dan kebetulan menjadi 1.234.567.890 dalam alfabet angka-lalu-huruf-kecil, karena urutan itu persis sama dengan angka-dulu dengan kedua kasus huruf ditukar. Karakter nol juga tidak dipakai bersama: dua urutan angka-dulu menulis nol sebagai 0, sedangkan urutan huruf-dulu menulisnya sebagai A, sehingga alfabet itu tidak diawali digit sama sekali.
Base62 dibandingkan dengan encoding lain
| Encoding | Bit per karakter | Ukuran dibanding input | Catatan |
| Base16 (hex) | 4 | 200% | Dua karakter per byte, sangat mudah dibaca, tanpa alfabet yang perlu dicari. |
| Base32 | 5 | 160% | Tidak peka huruf besar-kecil dan aman untuk didiktekan, paling boros dalam kelompoknya. |
| Base36 (0-9 a-z) | ~5,17 | ~155% | Hanya digit dan huruf kecil, sehingga tetap aman melalui pipeline yang mengubah huruf kecil. 12345 menjadi 9ix. |
| Base58 | ~5,86 | ~137% | Dipilih untuk alamat, bukan untuk kepadatan: empat karakter yang mirip dibuang alih-alih diurutkan. Lihat Base32 / Base58. |
| Base62 | ~5,95 | ~134% | Setiap karakter adalah digit atau huruf, sehingga tidak ada yang perlu di-escape. Kepadatannya berada di antara Base58 dan Base64. |
| Base64 | 6 | 133% | Default di mana-mana, dengan konsekuensi +, /, dan =, tiga karakter yang memaksa escaping. Lihat Konverter Base64. |
| Ascii85 / Base85 | 6,4 | 125% | 5 karakter per 4 byte, tetapi membagi dengan 85 dan alfabetnya memerlukan tanda kutip. Lihat Ascii85. |
| Base91 | ~6,5 | ~123% | Yang paling padat di antara ini, dan yang outputnya paling tidak aman untuk ditempel tanpa escaping. Lihat Base91. |
Persentase adalah biaya asimtotik yang dibulatkan; jumlah karakter yang diukur untuk satu input nyata 92 byte ada di tabel ukuran di bagian atas halaman ini. Dalam mode integer perbandingannya berbalik, karena input adalah teks desimal, bukan byte: di sana Base62 sekitar 44% lebih pendek daripada digit yang digantikannya, dan Base36 sekitar 36% lebih pendek, itulah sebabnya kode ID biasanya Base62 atau Base36, bukan Base58.
Apa yang bukan Base62
- Bukan standar. Tidak ada RFC dan tidak ada spesifikasi. Tidak ada badan standar yang pernah mendefinisikan Base62, itulah sebabnya alfabetnya tidak dijamin dan halaman ini mencetak ketiga urutan alih-alih memilih satu secara diam-diam.
- Bukan enkripsi. Ini hanyalah pergantian basis, tidak lebih. Siapa pun yang mengetahui alfabetnya dapat membaliknya dalam satu langkah, dan tidak ada kunci, salt, atau kerahasiaan apa pun.
- Bukan kompresi. Mode byte memperbesar data sekitar sepertiga. Mode integer hanya tampak seperti kompresi karena teks desimal memang cara yang tidak efisien untuk menulis angka.
- Tidak peka huruf besar-kecil. Base32 dapat diubah ke huruf kecil dan dibaca kembali; Base62 tidak bisa. Kode yang melewati sistem yang menormalkan huruf besar-kecil adalah kode yang rusak.
- Tidak memiliki pemeriksaan diri. Tidak ada checksum dan tidak ada karakter cek, sehingga satu karakter yang salah menghasilkan hasil yang tampak valid dengan nilai berbeda. Jika itu penting, urutan Bitcoin dilengkapi checksum — lihat bagian Base58Check di Base32 / Base58.
- Panjangnya tidak tetap. Jumlah karakter bertambah seiring nilainya, sehingga penghitung yang dimulai dari 1 dan mencapai 627 berubah dari satu karakter menjadi delapan. Beri padding ke lebar tetap bila diperlukan kolom yang stabil.
Jebakan yang benar-benar menyulitkan
- Alfabet menjawab sembilan dari sepuluh misteri. Jika alat lain memberi kode berbeda untuk angka yang sama, bandingkan kedua alfabet karakter demi karakter sebelum mencurigai bug. Tabel di atas menampilkan nilai yang sama dalam tiga alfabet, dan ketiganya benar.
- Alfabet yang salah gagal secara diam-diam. Tidak ada jalur error untuk itu:
3D7 didekode menjadi 12.345, 13.957, atau 211.665 hanya tergantung urutan mana yang diasumsikan. Periksa karakter pertama, yang paling mungkin merupakan padding nol, dan periksa apakah alfabet memiliki digit atau huruf di depan.
- Angka nol di depan memiliki dua arti. Dalam mode integer
00012345 dan 12345 adalah angka yang sama dan dicetak identik. Dalam mode byte byte nol di depan adalah data, dan dicetak sebagai satu karakter nol tambahan. Menghapus salah satu karakter itu mengubah string byte.
- Normalisasi huruf besar-kecil merusak kode. Alamat email, nama host, atau path Windows dapat diubah menjadi huruf kecil saat dikirim. Kode Base62 tidak bisa bertahan dari itu, dan itulah alasan Base36 masih ada.
- Input panjang itu lambat, bukan sekadar besar. Konversi adalah aritmetika atas seluruh input sekaligus, sehingga menggandakan panjang input melipatgandakan waktu empat kali. Halaman ini menolak input yang melewati batas terukurnya alih-alih membeku; tabel ukuran di atas memberikan angka yang diukur.
- String Base62 tidak membuktikan apa pun. Karena hampir setiap string digit dan huruf didekode tanpa keluhan, slug URL acak akan didekode menjadi suatu angka. Kode hanya bermakna jika sistem yang menerbitkannya juga menyimpan pemetaannya.
Jawaban singkat
“Mengapa alat Base62 lain memberi kode berbeda untuk angka yang sama?”
Karena alfabetnya berbeda. Base62 tidak memiliki spesifikasi yang bisa dijadikan pegangan, sehingga implementasi memilih urutan: angka dan huruf besar dulu, angka dan huruf kecil dulu, atau huruf sebelum angka. Ubah pemilih alfabet di bagian atas halaman ini untuk melihat ketiga jawaban berdampingan.
“Apakah Base62 aman di URL?”
Ya, pada ketiga urutan. Semua 62 karakter adalah huruf dan digit yang tidak di-escape, sehingga tidak satu pun diperluas menjadi tripel persen dalam query string, dan tidak satu pun mengakhiri URL, segmen path, atau atribut HTML. Itulah alasan utama tautan pendek memakai Base62, bukan Base64.
“Mana yang lebih kecil, Base62 atau Base64?”
Untuk byte, Base64 sedikit lebih kecil: sekitar 133% dari input dibanding sekitar 134%. Pada sampel 92 byte di atas, keduanya seri di 124 karakter. Untuk bilangan desimal, Base62 memperpendek teks sekitar 44%, dan di situlah keuntungan praktisnya.
“Bisakah string Base64 didekode dengan halaman ini?”
Tidak, dan ia tidak akan memberi tahu jika gagal. Kedua alfabet tumpang tindih di seluruh 62 karakter, sehingga string Base64 biasanya juga "valid" sebagai input di sini dan hanya didekode menjadi angka yang berbeda. Gunakan Base64 untuk Base64.
“Apakah kode Base62 memiliki panjang maksimum?”
Secara teori algoritmanya tidak punya batas. Dalam praktiknya halaman ini berhenti di 4.096 digit desimal, atau 2.048 byte, karena aritmetika di baliknya kuadratik dan tab akan membeku tanpa apa pun di layar untuk menjelaskan alasannya. Tabel batas di bagian atas halaman ini mencantumkan angka yang diukur.
“Bagaimana memastikan hasil di halaman ini benar?”
Tekan Uji mandiri. Ini menjalankan setiap contoh yang didokumentasikan, setiap panjang byte dari 0 hingga 64, dan sebaran angka desimal di ketiga alfabet, membandingkan nilai yang dikembalikan dengan input, dan memeriksa ulang bahwa 62 karakter setiap alfabet aman di URL. Tombol Contoh juga membandingkan ketiga hasilnya dengan nilai yang tercatat dalam file data halaman ini, yang diverifikasi terhadap implementasi bilangan bulat besar kedua yang independen dan disimpan dalam perkakas uji situs ini.
Standar dan kredit
Tidak ada standar untuk diimplementasikan di sini: Base62 adalah konvensi, bukan spesifikasi, dan ketiga alfabet yang dicetak di atas adalah yang muncul dalam perangkat lunak nyata. Halaman ini mengimplementasikannya dengan rutin bilangan bulat besar milik situs, yang ditulis dalam aritmetika biasa pada array digit sehingga tidak ada ukuran yang dibatasi oleh tipe angka JavaScript.
Teks halaman ini ditulis untuk situs ini. Setiap contoh yang dikerjakan di halaman ini dihasilkan oleh kode halaman itu sendiri lalu diverifikasi terhadap implementasi kedua yang independen yang memakai bilangan bulat besar native, dan implementasi itu disimpan dalam perkakas uji situs ini; implementasi yang sama juga memverifikasi tabel contoh dan ukuran dalam file data.