Ce este Base62?
Base62 este un mod de a scrie un număr cu nimic altceva decât caractere care supraviețuiesc lipirii oriunde: cele zece cifre, cele 26 de litere mari și cele 26 de litere mici. Fără semne de punctuație, fără spații, fără caracter de umplutură, nimic care trebuie escapat înainte de a intra într-un URL, un nume de fișier, un cookie sau o cheie de bază de date. Zece plus 26 plus 26 fac 62, și de aici vine numele.
Versiunea de 30 de secunde: numărul 12345 se scrie 3D7, iar 1234567890 se scrie 1LY7VK. Întoarcerea este aceeași operație în sens invers și are nevoie de alfabetul exact care a produs codul — un alt alfabet transformă aceleași șase caractere într-un alt număr, fără nicio eroare afișată.
Această pagină face două lucruri înrudite, iar diferența dintre ele contează mai mult decât orice altceva de pe pagină:
- Modul întreg tratează intrarea ca pe un număr. Un ID zecimal precum
1234567890 devine 1LY7VK, iar zerourile de la începutul intrării nu fac parte din valoare, deci nu se mai întorc.
- Modul octeți tratează intrarea ca pe un șir de octeți. Octeții se citesc ca un singur număr uriaș, big-endian, și apoi se împart la 62, adică aceeași aritmetică aplicată altei mărimi. Aici numărul de octeți zero de la început se păstrează, câte un caracter zero pentru fiecare octet zero.
De unde vin cei 62 și ce costă
62 nu este o putere a lui doi, iar acest singur fapt modelează tot restul. Codificările familiare sunt construite prin tăierea intrării în grupuri fixe de biți: 4 biți devin un caracter hexazecimal, 6 biți un caracter Base64, 5 biți un caracter Base32. Base62 nu poate face asta, pentru că niciun număr întreg de biți nu încape într-un caracter cu 62 de valori — 5 biți numesc doar 32 de valori, iar 6 biți numesc 64. Așa că Base62 trece prin aritmetică: se citește întreaga intrare ca un singur întreg și se tipărește în baza 62.
Un caracter transportă atunci log2(62) = 5,954 biți, foarte aproape de cei 6 ai Base64, iar în modul zecimal un caracter înlocuiește log62(10) = 1,792 cifre zecimale. Câteva consecințe care merită cunoscute înainte de a alege o lungime:
| Lungimea codului | Valorile pe care le poate numi | În practică |
| 4 caractere | 624 = 14 776 336 | Suficient pentru un contor care rămâne sub opt cifre și încape în spațiul unui număr de telefon. |
| 6 caractere | 626 = 56 800 235 584 | Forma obișnuită a unui cod de ID. Un ID zecimal de zece cifre încape în șase caractere. |
| 7 caractere | 627 = 3 521 614 606 208 | Peste intervalul unui contor pe 32 de biți cu două ordine de mărime, în lățimea unui slug scurt de link. |
| 11 caractere | 6211 = 52 036 560 683 837 093 888 | Mai mult decât 264 = 18 446 744 073 709 551 616, deci un număr complet pe 64 de biți încape în unsprezece caractere. |
Invers, 1 000 de cifre zecimale au nevoie de aproximativ 558 de caractere, iar 4 096 de cifre zecimale au nevoie de 2 285. Economia este reală, dar limitată: Base62 scurtează un număr zecimal cu aproximativ 44%, și nu întrece niciodată cele mai dense codificări tipăribile, pentru că 5,954 biți pe caracter sunt pur și simplu mai puțin decât 6,4 sau 6,5.
Modul întreg: ce se întâmplă cu zerourile de la început
Un întreg are o singură formă scrisă canonică, iar aceasta începe cu caracterul zero al alfabetului, care este 0 în cele două ordini cu cifrele întâi și A în ordinea cu literele întâi. Tot ce se află înaintea primului caracter semnificativ este umplutură, iar umplutura nu face parte din valoare: 00012345 și 12345 devin amândouă 3D7. Dacă se dorește o lățime fixă — de exemplu un cod de șapte caractere care trebuie aliniat într-o coloană — caseta Completează rezultatul la o lățime fixă de pe pagină repetă caractere zero până se atinge lățimea, astfel încât 12345 la lățimea 7 se tipărește 00003D7 în alfabetul cu cifrele întâi și AAAADNH în cel cu literele întâi. Umplutura este cosmetică: caracterele de la început nu adaugă nimic valorii, iar decodarea oricăruia dintre șiruri dă înapoi 12345, pentru că 0 × 626 și 0 × 625 sunt amândouă zero, indiferent ce caracter scrie zeroul.
Decodarea unui șir completat funcționează, deci, și ea, iar pagina raportează câte dintre caracterele de la început au fost zerouri, astfel încât diferența dintre „codul are șapte caractere” și „valoarea a avut nevoie de trei caractere” să nu fie niciodată un mister.
Modul octeți: aceeași aritmetică pe un șir de octeți
Modul octeți citește octeții de intrare ca un singur întreg big-endian — întregul șir de octeți este tratat ca un singur număr, oricât de lung ar fi — și tipărește acel număr în baza 62. Deoarece un octet conține 8 biți, iar un caracter ține 5,954 dintre ei, modul octeți nu este compresie: are nevoie de aproximativ 134% din dimensiunea intrării, puțin mai rău decât cei 133% ai Base64. Pe exemplul de 92 de octeți din tabelul de dimensiuni de mai sus, 92 de octeți se tipăresc în 124 de caractere Base62, iar Base64 tipărește tot 124 (123 dintre ele înainte de umplutura =). Base62 pierde în fața Base64 la densitate și câștigă la siguranța caracterelor, iar acesta este compromisul pe care îl face fiecare link scurt și fiecare cod de invitație, în mod deliberat.
Octeții zero de la început se păstrează, iar acest lucru este ușor de greșit în ambele sensuri. Doi octeți zero de la început, plus 0x01, se tipăresc ca 001 în alfabetul cu cifrele întâi și ca AAB în cel cu literele întâi, pentru că caracterele de la început scriu zero, câte unul pentru fiecare octet zero. Un șir de octeți format dintr-un singur 0x00 se tipărește ca un singur caracter 0, iar un șir format dintr-un singur 0x01 se tipărește ca 1. Acesta este singurul loc unde modul octeți și modul întreg arată diferit, deși rulează același algoritm.
Costul întregii situații este că modul octeți moștenește timpul pătratic al aritmeticii: pentru 1 024 de octeți se estimează aproximativ o treime de secundă, iar pentru 2 048 de octeți aproximativ 1,3 secunde, aceleași cifre ca în tabelul de limite de mai sus. De aceea modul octeți de aici este limitat la 2 048 de octeți la intrare și la 2 048 de caractere la ieșire — 2 048 de octeți se tipăresc în aproximativ 2 751 de caractere, deci aproximativ 1 520 de octeți este cea mai mare sarcină utilă care supraviețuiește unui dus-întors prin această pagină — și de aceea modul octeți de pe această pagină este o referință pentru valori mici, nu un înlocuitor pentru Base64 sau Base91 pentru fișiere reale.
Cele trei alfabete și de ce alfabetul este întreaga poveste
Caracterele unui alfabet sunt o secvență fixă, iar valoarea unui caracter este poziția sa în această secvență. Mutarea secvenței schimbă ce înseamnă fiecare caracter. Sunt trei ordini în uz larg, iar acesta este același număr scris în fiecare dintre ele:
| Zecimal | 0-9 apoi A-Z apoi a-z | 0-9 apoi a-z apoi A-Z | A-Z apoi a-z apoi 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 |
Citite cele trei ultime coloane ca un singur alfabet, formează o schemă coerentă. Citite ca interschimbabile, se destramă, pentru că decodarea este oarbă la alfabet în cel mai rău mod: orice caracter al intrării se află în toate cele trei alfabete, deci un alfabet greșit nu produce nicio eroare, ci doar un alt număr.
| Un cod | Citit ca 0-9 A-Z a-z | Citit ca 0-9 a-z A-Z | Citit ca 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 |
Majusculele sunt o a doua versiune, mai ascuțită, a aceleiași capcane. Base62 este sensibil la majuscule în orice ordine, deci transformarea unui cod în litere mici îl rescrie în tăcere: 1LY7VK înseamnă 1 234 567 890 în alfabetul cu cifrele întâi, pe când 1ly7vk înseamnă 1 624 950 792 în același alfabet — și înseamnă 1 234 567 890 în alfabetul cu cifrele urmate de litere mici, pentru că această ordine este exact cea cu cifrele întâi, cu cele două tipuri de litere inversate. Nici caracterul zero nu este comun: cele două ordini cu cifrele întâi scriu zero ca 0, iar ordinea cu literele întâi îl scrie ca A, deci acest alfabet nu începe deloc cu o cifră.
Base62 alături de celelalte codificări
| Codificare | Biți pe caracter | Dimensiune față de intrare | Note |
| Base16 (hex) | 4 | 200% | Două caractere pe octet, citire trivială, fără alfabet de căutat. |
| Base32 | 5 | 160% | Insensibil la majuscule și sigur pentru dictare, cel mai risipitor din grup. |
| Base36 (0-9 a-z) | ~5,17 | ~155% | Doar cifre și litere mici, deci supraviețuiește unui pipeline care transformă în litere mici. 12345 este 9ix. |
| Base58 | ~5,86 | ~137% | Ales pentru adrese, nu pentru densitate: patru caractere care se confundă sunt eliminate, în loc să fie ordonate. Vezi Base32 / Base58. |
| Base62 | ~5,95 | ~134% | Fiecare caracter este o cifră sau o literă, deci nimic nu se escapează niciodată. Densitatea se află între Base58 și Base64. |
| Base64 | 6 | 133% | Implicit peste tot, cu prețul +, / și =, cele trei caractere care forțează escaparea. Vezi Convertor Base64. |
| Ascii85 / Base85 | 6,4 | 125% | 5 caractere la 4 octeți, dar împarte la 85 și alfabetul său trebuie pus între ghilimele. Vezi Ascii85. |
| Base91 | ~6,5 | ~123% | Cel mai dens dintre acestea și cel al cărui rezultat este cel mai puțin sigur de lipit fără escapare. Vezi Base91. |
Procentele sunt costuri asimptotice, rotunjite; numărul măsurat de caractere pentru o intrare reală de 92 de octeți se află în tabelul de dimensiuni de mai sus pe această pagină. În modul întreg, comparația merge în sens invers, pentru că intrarea este text zecimal, nu octeți: acolo Base62 este cu aproximativ 44% mai scurt decât cifrele pe care le înlocuiește, iar Base36 cu aproximativ 36% mai scurt, de aceea un cod de ID este de obicei Base62 sau Base36 și nu Base58.
Ce nu este Base62
- Nu este un standard. Nu există RFC și nicio specificație. Niciun organism de standardizare nu a definit vreodată Base62, de aceea alfabetul nu este garantat și de aceea această pagină tipărește toate cele trei ordini, în loc să aleagă una în tăcere.
- Nu este criptare. Este o schimbare de bază, nimic mai mult. Oricine cunoaște alfabetul o inversează într-o singură trecere, iar nu există nicio cheie, niciun salt și nicio formă de secretitate.
- Nu este compresie. Modul octeți mărește datele cu aproximativ o treime. Modul întreg doar pare compresie, pentru că textul zecimal este, din start, un mod ineficient de a scrie un număr.
- Nu este insensibil la majuscule. Base32 poate fi scris cu litere mici și citit înapoi; Base62 nu. Un cod care trece printr-un sistem care normalizează majusculele este un cod corupt.
- Nu se autoverifică. Nu există sumă de control și nici caracter de control, așa că un singur caracter greșit dă un rezultat valid la aspect, dar cu altă valoare. Dacă asta contează, ordinea Bitcoin vine cu o sumă de control — vezi secțiunea Base58Check din Base32 / Base58.
- Nu are lungime fixă. Numărul de caractere crește odată cu valoarea, așa că un contor care pornește de la 1 și ajunge la 627 trece de la un caracter la opt. Se completează la o lățime fixă atunci când este nevoie de o coloană stabilă.
Capcane care chiar mușcă
- Alfabetul este răspunsul la nouă din zece mistere. Dacă un alt instrument dă un cod diferit pentru același număr, se compară cele două alfabete caracter cu caracter, înainte de a bănui o eroare. Tabelul de mai sus arată aceeași valoare în trei alfabete, iar toate trei sunt corecte.
- Un alfabet greșit eșuează în tăcere. Nu există o cale de eroare pentru asta:
3D7 se decodează în 12 345, 13 957 sau 211 665, în funcție doar de ordinea presupusă. Se verifică primul caracter, cel mai probabil să fie o umplutură cu zero, și dacă alfabetul are cifre sau litere la început.
- Zerourile de la început înseamnă două lucruri diferite. În modul întreg,
00012345 și 12345 sunt același număr și se tipăresc identic. În modul octeți, un octet zero de la început este date, și se tipărește ca un caracter zero în plus. Eliminarea unuia dintre acele caractere schimbă șirul de octeți.
- Normalizarea majusculelor distruge un cod. O adresă de e-mail, un nume de gazdă sau o cale Windows pot fi transformate în litere mici în tranzit. Un cod Base62 nu poate supraviețui asta, și de aceea încă există Base36.
- Intrările lungi sunt lente, nu doar mari. Conversia este aritmetică pe întreaga intrare deodată, deci dublarea lungimii intrării înmulțește timpul cu patru. Pagina refuză intrările peste limitele sale măsurate, în loc să se blocheze; tabelul dimensiunilor de mai sus dă cifrele măsurate.
- Un șir Base62 nu dovedește nimic. Deoarece aproape orice șir de cifre și litere se decodează fără obiecții, un slug arbitrar de URL se va decoda într-un anumit număr. Un cod are sens doar dacă sistemul care l-a emis stochează și maparea.
Răspunsuri rapide
„De ce dă un alt instrument Base62 un alt cod pentru același număr?”
Pentru că alfabetul diferă. Base62 nu are o specificație cu care să intre în contradicție, deci implementările aleg o ordine: cifrele și literele mari primele, cifrele și literele mici primele sau literele înaintea cifrelor. Selectorul de alfabet din partea de sus a paginii se schimbă, pentru a vedea alăturat toate cele trei răspunsuri.
„Este Base62 sigur într-un URL?”
Da, în toate cele trei ordini. Toate cele 62 de caractere sunt litere și cifre neescapate, deci niciunul nu este extins într-un triplet procentual într-un șir de interogare și niciunul nu încheie un URL, un segment de cale sau un atribut HTML. Acesta este motivul întreg pentru care link-urile scurte sunt în Base62, și nu în Base64.
„Care este mai mic, Base62 sau Base64?”
Pentru octeți, Base64 este foarte puțin mai mic: aproximativ 133% din intrare, față de aproximativ 134%. Pe exemplul de 92 de octeți de mai sus, cele două ajung la egalitate, cu 124 de caractere. Pentru numere zecimale, Base62 scurtează textul cu aproximativ 44%, și acolo este câștigul practic.
„Pot decoda un șir Base64 cu această pagină?”
Nu, și nu va semnala că a eșuat. Cele două alfabete se suprapun în toate cele 62 de caractere, așa că un șir Base64 este de obicei și el „valid” ca intrare aici și pur și simplu se decodează într-un alt număr. Pentru Base64 se folosește Base64.
„Are un cod Base62 o lungime maximă?”
Nu, în teorie algoritmul nu are o limită. În practică, pagina se oprește la 4 096 de cifre zecimale, sau 2 048 de octeți, pentru că aritmetica din spatele ei este pătratică, iar fila ar îngheța fără să existe nimic pe ecran care să explice de ce. Tabelul de limite de mai sus de pe această pagină listează cifrele măsurate.
„De unde știu că rezultatul de pe această pagină este corect?”
Se apasă Autotest. Rulează fiecare exemplu documentat, fiecare lungime de octeți de la 0 la 64 și o serie de numere zecimale în toate cele trei alfabete, compară valorile returnate cu ce a intrat și verifică din nou că toate cele 62 de caractere ale fiecărui alfabet sunt sigure într-un URL. Butonul Exemplu compară, în plus, cele trei rezultate ale sale cu valorile înregistrate în fișierul de date al paginii, care au fost verificate față de o a doua implementare independentă cu numere mari, păstrată în uneltele de testare ale acestui site.
Standarde și creditare
Nu există un standard de implementat aici: Base62 este o convenție, nu o specificație, iar cele trei alfabete tipărite mai sus sunt cele care apar în software-ul real. Această pagină îl implementează cu rutinele proprii ale site-ului pentru numere mari, scrise în aritmetică simplă pe tablouri de cifre, astfel încât nicio dimensiune să nu fie limitată vreodată de tipul numeric JavaScript.
Textul paginii a fost scris pentru acest site. Fiecare exemplu lucrat de pe această pagină a fost produs de codul paginii și apoi verificat față de o a doua implementare independentă, care folosește numere mari native și este păstrată în uneltele de testare ale acestui site; aceeași implementare a verificat și tabelele de exemple și de dimensiuni din fișierul de date.