Base62 coderen / decoderen

Converteer een getal of een bytereeks met Base62: 62 tekens bestaande uit cijfers, hoofdletters en kleine letters, waarvan geen enkele hoeft te worden ge-escaped in een URL-query of in HTML-tekst. Daarom worden korte links en auto-increment-ID's zo geschreven. Twee modi: een decimaal getal (een ID wordt een korte code) en bytes (tekst of hexadecimale invoer). Ook: Base64 | Base32 / Base58 | Base91.
Alle verwerking gebeurt lokaal in uw browser — uw gegevens worden nooit naar een server geüpload.

Nog nooit van Base62 gehoord? Wat is Base62 — in gewone taal uitgelegd (met uitgewerkte voorbeelden, de drie alfabetten en de valkuilen).
Alfabet:
Resultaat opvullen tot vaste breedte: 0 = geen opvulling. Opvulling herhaalt het nulteken van het gekozen alfabet, dus hetzelfde getal wordt in het alfabet met letters eerst anders opgevuld.
Hoe het werkt:
Invoer is:
Hoe het werkt:
Uitvoer als:
Ctrl+Enter in de invoer voert de actieve modus uit.
Kies Coderen of Decoderen en klik op de actieknop. De knop Zelftest draait elk gedocumenteerd voorbeeld, elke lengte van 0 tot 64 bytes en een spreiding van decimale getallen over alle drie de alfabetten, en meldt het aantal hier.
De drie alfabetten, volledig afgedrukt: Base62 heeft geen standaardisatie-instantie achter zich, dus het alfabet is niet gegarandeerd over implementaties heen. Dit zijn de drie volgordes die in het wild voorkomen; elk is teken voor teken afgedrukt met zijn waarde, zodat elk resultaat terug te traceren is naar het exacte alfabet dat het voortbracht. De gearceerde cel is het teken dat nul betekent, en dat is niet in alle drie hetzelfde teken.
Base62 is in elk van de drie volgordes hoofdlettergevoelig: een hoofdletter en de kleine-letter-vorm ervan benoemen bijna altijd verschillende waarden, dus een code die een stap met kleine letters heeft doorlopen, is een ander getal, geen fout.
Base62 is in elk van de drie volgordes hoofdlettergevoelig: een hoofdletter en de kleine-letter-vorm ervan benoemen bijna altijd verschillende waarden, dus een code die een stap met kleine letters heeft doorlopen, is een ander getal, geen fout.
Lengte van dezelfde bytes in elke codering:
Hoe groot een invoer deze pagina accepteert, en waarom: elke modus hier converteert via één groot geheel getal, en grootgetalconversie kost tijd evenredig aan het kwadraat van de lengte. Dat is een eigenschap van het formaat zelf, niet van deze pagina: elk hulpmiddel dat echte Base62 implementeert, heeft dezelfde vorm van limiet. De getallen hieronder komen uit een timingtest die de eigen routines van de pagina draait en niet uit een lopend tabblad, en ze zijn daarom bewust aan de pessimistische kant: een desktopbrowser eindigt meestal meerdere keren sneller, en die marge dekt een trage telefoon. De limieten zijn zo gezet dat zelfs het trage geval klaar is in plaats van het tabblad te laten vastlopen.
Boven de zachte limiet legt de eerste klik de kosten uit en vraagt om een tweede klik voordat het loopt; boven de harde limiet weigert de pagina in plaats van het tabblad enkele seconden vast te laten lopen zonder voortgang te tonen. Bytemodus wordt geteld in bytes bij het coderen en in tekens bij het decoderen, en het aantal tekens is altijd het grootste: 2.048 bytes worden ongeveer 2.751 tekens, wat boven de tekenlimiet ligt, dus een lading van ongeveer 1.520 bytes of minder is wat een heen-en-terugreis op deze pagina overleeft. Voor gewone binaire data van enige echte omvang zijn Base64 en Base91 lineair en kennen ze zo'n limiet niet.
Wat is Base62?

Base62 is een manier om een getal te schrijven met alleen de tekens die overleven als ze overal worden geplakt: de tien cijfers, de 26 hoofdletters en de 26 kleine letters. Geen leestekens, geen spaties, geen opvultekens, niets dat moet worden ge-escaped voordat het in een URL, bestandsnaam, cookie of databasesleutel terechtkomt. Tien plus 26 plus 26 is 62, en daar komt de naam vandaan.

De versie van 30 seconden: het getal 12345 wordt geschreven als 3D7, en 1234567890 wordt geschreven als 1LY7VK. De andere kant op is dezelfde bewerking omgekeerd, en die heeft het exacte alfabet nodig dat de code heeft voortgebracht — een ander alfabet maakt van dezelfde zes tekens een ander getal terug, zonder enige foutmelding.

Deze pagina doet twee verwante taken, en het verschil tussen die twee is belangrijker dan al het andere op deze pagina:

  • Gehele-getallenmodus behandelt de invoer als een getal. Een decimaal ID zoals 1234567890 wordt 1LY7VK, en de voorloopnullen van de invoer maken geen deel uit van de waarde, dus die komen niet terug.
  • Bytemodus behandelt de invoer als een bytereeks. De bytes worden gelezen als één enorm big-endian getal en daarna gedeeld door 62 — dezelfde rekenkunde op een andere grootheid. Hier overleeft het aantal voorloopnulbytes wel, één nulbyte per nulteken.
Waar de 62 vandaan komt, en wat het kost

62 is geen macht van twee, en dat ene feit bepaalt alles verder. De bekende coderingen worden gebouwd door de invoer in vaste bitgroepen te snijden: 4 bits drukken als één hexadecimaal teken, 6 bits als één Base64-teken, 5 bits als één Base32-teken. Base62 kan dat niet, omdat geen heel aantal bits past bij een teken met 62 waarden — 5 bits benoemen maar 32 waarden, 6 bits 64. Daarom gaat Base62 via rekenkunde: lees de hele invoer als één geheel getal en druk dat af in grondtal 62.

Eén teken draagt dan log2(62) = 5,954 bits, wat heel dicht bij de 6 van Base64 ligt, en in decimale modus vervangt één teken log62(10) = 1,792 decimale cijfers. Enkele gevolgen om te weten voordat u een lengte kiest:

Lengte van de codeWaarden die het kan benoemenIn de praktijk
4 tekens624 = 14.776.336Genoeg voor een teller die onder acht cijfers blijft, en het past in de ruimte van een telefoonnummer.
6 tekens626 = 56.800.235.584De gebruikelijke vorm van een ID-code. Een tiencijferig decimaal ID past in zes tekens.
7 tekens627 = 3.521.614.606.208Twee ordes van grootte voorbij het bereik van een teller van 32 bits, in de breedte van een korte link-slug.
11 tekens6211 = 52.036.560.683.837.093.888Meer dan 264 = 18.446.744.073.709.551.616, dus een volledig getal van 64 bits past in elf tekens.

Andersom gelezen: 1.000 decimale cijfers hebben ongeveer 558 tekens nodig, en 4.096 decimale cijfers hebben er 2.285 nodig. De besparing is reëel maar begrensd: Base62 verkort een decimaal getal met ruwweg 44%, en het verslaat nooit de dichtste afdrukbare coderingen, omdat 5,954 bits per teken eenvoudigweg minder is dan 6,4 of 6,5.

Gehele-getallenmodus: wat er met voorloopnullen gebeurt

Een geheel getal heeft één kanonieke geschreven vorm en die begint met het nulteken van het alfabet, dat 0 is in de twee volgordes met cijfers eerst en A in de volgorde met letters eerst. Alles links van het eerste significante teken is opvulling, en opvulling hoort niet bij de waarde: 00012345 en 12345 worden allebei 3D7. Als een vaste breedte gewenst is — bijvoorbeeld een code van zeven tekens die in een kolom moet uitlijnen — herhaalt het vak Resultaat opvullen tot vaste breedte van de pagina nultekens tot de breedte is bereikt, zodat 12345 op breedte 7 00003D7 drukt in het alfabet met cijfers eerst en AAAADNH in het alfabet met letters eerst. Opvulling is cosmetisch: die voorlooptekens voegen niets toe aan de waarde, en decoderen van beide tekenreeksen geeft 12345 terug, omdat 0 × 626 en 0 × 625 allebei nul zijn, wat het nulteken ook is.

Het decoderen van een opgevulde tekenreeks werkt dus ook, en de pagina meldt hoeveel van de voorlooptekens nultekens waren, zodat het verschil tussen "de code is zeven tekens" en "de waarde had drie tekens nodig" nooit een raadsel is.

Bytemodus: dezelfde rekenkunde op een bytereeks

Bytemodus leest de invoerbytes als één big-endian geheel getal — de hele bytereeks wordt als één getal behandeld, hoe lang die ook is — en drukt dat getal af in grondtal 62. Omdat een byte 8 bits bevat en een teken er 5,954 benoemt, is bytemodus geen compressie: het heeft ongeveer 134% van de invoergrootte nodig, net iets slechter dan de 133% van Base64. Bij het monster van 92 bytes dat in de groottetabel hierboven wordt gebruikt, drukken 92 bytes af als 124 Base62-tekens, en Base64 drukt ook 124 af (123 ervan vóór de =-opvulling). Base62 verliest van Base64 op dichtheid en wint op tekenveiligheid, en dat is de afweging die elke korte link en uitnodigingscode bewust maakt.

Voorloopnulbytes blijven behouden, en dat is in beide richtingen makkelijk fout te doen. Twee voorloopnulbytes gevolgd door 0x01 drukken af als 001 in het alfabet met cijfers eerst en als AAB in het alfabet met letters eerst, omdat de voorlooptekens nul voorstellen en er één is per nulbyte. Een bytereeks die alleen uit 0x00 bestaat, drukt het enkele teken 0 af, en een bytereeks die alleen uit 0x01 bestaat, drukt 1 af. Dit is de enige plek waar bytemodus en gehele-getallenmodus er verschillend uitzien terwijl ze hetzelfde algoritme draaien.

De prijs hiervan is dat bytemodus de kwadratische tijdsduur van de rekenkunde erft: 1.024 bytes duren naar schatting ongeveer een derde seconde en 2.048 bytes ongeveer 1,3 seconde, dezelfde cijfers die de limieten-tabel hierboven geeft. Daarom is bytemodus hier beperkt tot 2.048 bytes bij het coderen en tot 2.048 tekens bij het terugdecoderen — 2.048 bytes worden ongeveer 2.751 tekens, dus ongeveer 1.520 bytes is de grootste lading die een heen-en-terugreis via deze pagina overleeft — en daarom is de bytemodus op deze pagina een referentie voor kleine waarden, geen vervanging van Base64 of Base91 voor echte bestanden.

De drie alfabetten, en waarom het alfabet het hele verhaal is

De tekens van een alfabet vormen een vaste reeks, en de waarde van een teken is zijn positie in die reeks. De reeks verplaatsen verandert wat elk teken betekent. Drie volgordes zijn wijdverbreid in gebruik, en dit is hetzelfde getal in elk van de drie geschreven:

Decimaal0-9 dan A-Z dan a-z0-9 dan a-z dan A-ZA-Z dan a-z dan 0-9
000A
61zZ9
621010BA
12.3453D73d7DNH
1.234.567.8901LY7VK1ly7vkBViHfU

Lees de laatste drie kolommen als één alfabet en het is één samenhangend schema. Lees ze als inwisselbaar en het valt uit elkaar, omdat decoderen alfabetblind is op de slechtst mogelijke manier: elk teken van de invoer zit in alle drie de alfabetten, dus een verkeerd alfabet levert helemaal geen fout op, alleen een ander getal.

Een codeGelezen als 0-9 A-Z a-zGelezen als 0-9 a-z A-ZGelezen als A-Z a-z 0-9
3D712.34513.957211.665
1LY7VK1.234.567.8901.624.950.79248.723.527.772

Hoofdletters zijn een tweede, scherpere versie van dezelfde valkuil. Base62 is in elke volgorde hoofdlettergevoelig, dus een code in kleine letters zetten herschrijft haar stilzwijgend: 1LY7VK is 1.234.567.890 in het alfabet met cijfers eerst, terwijl 1ly7vk in datzelfde alfabet 1.624.950.792 is — en het is toevallig 1.234.567.890 in het alfabet met cijfers, dan kleine letters, omdat die volgorde precies het alfabet met cijfers eerst is met de twee lettersoorten omgewisseld. Het nulteken wordt ook niet gedeeld: de twee volgordes met cijfers eerst schrijven nul als 0, de volgorde met letters eerst als A, dus dat alfabet begint helemaal niet met een cijfer.

Base62 naast de andere coderingen
CoderingBits per tekenGrootte ten opzichte van de invoerOpmerkingen
Base16 (hex)4200%Twee tekens per byte, triviaal leesbaar, geen alfabet om op te zoeken.
Base325160%Hoofdletterongevoelig en veilig om te dicteren, de verspillendste van de groep.
Base36 (0-9 a-z)~5,17~155%Alleen cijfers en kleine letters, dus het overleeft een pijplijn die hoofdletters normaliseert. 12345 is 9ix.
Base58~5,86~137%Gekozen voor adressen, niet voor dichtheid: vier op elkaar lijkende tekens worden weggelaten in plaats van geordend. Zie Base32 / Base58.
Base62~5,95~134%Elk teken is een cijfer of een letter, dus niets wordt ooit ge-escaped. De dichtheid ligt tussen Base58 en Base64 in.
Base646133%De standaard overal, ten koste van +, / en =, de drie tekens die escapen afdwingen. Zie Base64-converter.
Ascii85 / Base856,4125%5 tekens per 4 bytes, maar het deelt door 85 en het alfabet moet tussen aanhalingstekens. Zie Ascii85.
Base91~6,5~123%De dichtste van deze, en degene waarvan de uitvoer het minst veilig is om ongeëscaped te plakken. Zie Base91.

De percentages zijn asymptotische kosten, afgerond; de gemeten tekenaantallen voor één echte invoer van 92 bytes staan in de tabel met groottes hierboven op deze pagina. In gehele-getallenmodus loopt de vergelijking andersom, omdat de invoer decimale tekst is en geen bytes: daar is Base62 ongeveer 44% korter dan de cijfers die het vervangt, en Base36 ongeveer 36% korter, en daarom is een ID-code meestal Base62 of Base36 en niet Base58.

Wat Base62 niet is
  • Geen standaard. Er is geen RFC en geen specificatie. Geen enkele standaardisatie-instantie heeft ooit Base62 gedefinieerd, en daarom is het alfabet niet gegarandeerd en drukt deze pagina alle drie de volgordes af in plaats van er stilzwijgend één te kiezen.
  • Geen versleuteling. Het is een grondtalwijziging, meer niet. Wie het alfabet kent, draait het in één keer terug, en er is geen sleutel, geen zout en geen enkele geheimhouding.
  • Geen compressie. Bytemodus maakt de data ongeveer een derde groter. Gehele-getallenmodus lijkt alleen op compressie omdat decimale tekst op zich een inefficiënte manier is om een getal te schrijven.
  • Niet hoofdletterongevoelig. Base32 kan in kleine letters worden gezet en teruggelezen; Base62 niet. Een code die door een systeem reist dat hoofdletters normaliseert, is een beschadigde code.
  • Geen zelfcontrole. Er is geen controlesom en geen controleteken, dus één verkeerd teken geeft een geldig ogend resultaat met een andere waarde. Als dat ertoe doet, komt de Bitcoin-volgorde met een controlesom — zie het Base58Check-gedeelte van Base32 / Base58.
  • Geen vaste lengte. Het aantal tekens groeit met de waarde, dus een teller die bij 1 begint en 627 bereikt, gaat van één teken naar acht. Vul aan tot een vaste breedte wanneer een stabiele kolom nodig is.
Valkuilen die echt bijten
  • Het alfabet is het antwoord op negen van de tien raadsels. Als een ander hulpmiddel een andere code geeft voor hetzelfde getal, vergelijk dan de twee alfabetten teken voor teken voordat u een bug vermoedt. De tabel hierboven toont dezelfde waarde in drie alfabetten, en alle drie zijn correct.
  • Een verkeerd alfabet faalt stilzwijgend. Er is geen foutpad voor: 3D7 decodeert naar 12.345, 13.957 of 211.665, uitsluitend afhankelijk van welke volgorde er wordt aangenomen. Controleer het eerste teken, dat het meest waarschijnlijk een nulopvulling is, en of het alfabet cijfers of letters vooraan heeft.
  • Voorloopnullen betekenen twee verschillende dingen. In gehele-getallenmodus zijn 00012345 en 12345 hetzelfde getal en drukken ze identiek af. In bytemodus is een voorloopnulbyte data, en die drukt als één extra nulteken af. Het weglaten van zo'n teken verandert de bytereeks.
  • Normalisatie van hoofdletters vernietigt een code. Een e-mailadres, een hostnaam of een Windows-pad kan onderweg in kleine letters worden gezet. Een Base62-code overleeft dat niet, en daarom bestaat Base36 nog steeds.
  • Lange invoer is traag, niet alleen groot. De conversie is rekenkunde op de volledige invoer in één keer, dus het verdubbelen van de invoerlengte verviervoudigt de tijd. Deze pagina weigert invoer boven de gemeten limieten in plaats van vast te lopen; de groottetabel hierboven geeft de gemeten getallen.
  • Een Base62-tekenreeks is geen bewijs van iets. Omdat bijna elke reeks cijfers en letters zonder klachten decodeert, decodeert een willekeurige URL-slug naar een getal. Een code betekent alleen iets als het systeem dat haar uitgaf ook de koppeling opslaat.
Korte antwoorden

“Waarom geeft een ander Base62-hulpmiddel een andere code voor hetzelfde getal?”

Omdat het alfabet verschilt. Base62 heeft geen specificatie waarmee gedisputeerd kan worden, dus implementaties kiezen een volgorde: cijfers en hoofdletters eerst, cijfers en kleine letters eerst, of letters vóór cijfers. Schakel in de alfabetkeuze bovenaan deze pagina om alle drie de antwoorden naast elkaar te zien.

“Is Base62 veilig in een URL?”

Ja, in elk van de drie volgordes. Alle 62 tekens zijn niet-ge-escapete letters en cijfers, dus geen van hen wordt uitgebreid tot een procentdrietal in een queryreeks, en geen van hen beëindigt een URL, een padsegment of een HTML-attribuut. Dat is de volledige reden dat korte links Base62 zijn en niet Base64.

“Wat is kleiner, Base62 of Base64?”

Voor bytes is Base64 iets kleiner: ongeveer 133% van de invoer tegen ongeveer 134% voor Base62. Bij het monster van 92 bytes hierboven zijn de twee gelijk met 124 tekens. Voor decimale getallen verkort Base62 de tekst met ongeveer 44%, en daar zit de praktische winst.

“Kan ik met deze pagina een Base64-tekenreeks decoderen?”

Nee, en het zal niet melden dat het is mislukt. De twee alfabetten overlappen in alle 62 tekens, dus een Base64-tekenreeks is hier meestal ook geldige invoer en decodeert gewoon naar een ander getal. Gebruik Base64 voor Base64.

“Heeft een Base62-code een maximale lengte?”

Nee. In theorie heeft het algoritme geen grens. In de praktijk stopt deze pagina bij 4.096 decimale cijfers, of 2.048 bytes, omdat de rekenkunde erachter kwadratisch is en het tabblad zou vastlopen zonder iets op het scherm dat uitlegt waarom. De limieten-tabel hierboven op deze pagina geeft de gemeten getallen.

“Hoe weet ik dat het resultaat op deze pagina klopt?”

Druk op Zelftest. Die draait elk gedocumenteerd voorbeeld, elke bytelengte van 0 tot 64 en een spreiding van decimale getallen over alle drie de alfabetten, vergelijkt de teruggegeven waarden met wat er in ging, en controleert opnieuw dat de 62 tekens van elk alfabet allemaal veilig zijn in een URL. De knop Voorbeeld vergelijkt bovendien zijn drie resultaten met de waarden die in het datamodule van deze pagina zijn vastgelegd, die zijn geverifieerd tegen een tweede, onafhankelijke implementatie met grote gehele getallen, bewaard in de testtools van deze site.

Standaarden en naamsvermelding

Er is hier geen standaard om te implementeren: Base62 is een conventie, geen specificatie, en de drie hierboven afgedrukte alfabetten zijn de alfabetten die in echte software voorkomen. Deze pagina implementeert het met de grote-gehele-getallenroutines van de site, geschreven als gewone rekenkunde op cijferarrays, zodat geen grootte ooit wordt beperkt door het JavaScript-getaltype.

De paginatekst is voor deze site geschreven. Elk uitgewerkt voorbeeld op deze pagina is gemaakt door de eigen code van de pagina en daarna geverifieerd tegen een tweede, onafhankelijke implementatie met native grote gehele getallen, die in de testtools van deze site wordt bewaard; dezelfde implementatie heeft de voorbeeld- en groottetabellen in het datamodule geverifieerd.