Hva er Base91?
Base91 er en måte å skrive vilkårlige byte på med bare utskrivbare ASCII-tegn, den samme jobben som Base64 gjør, men den passer flere bit inn i hvert tegn. I stedet for å hugge inndataene i 6-bitgrupper og skrive ut ett tegn per gruppe, samler den bit til den har minst 13 av dem, og skriver deretter ut to tegn som til sammen navngir verdien til disse 13 (eller 14) bitene.
To tegn fra et alfabet på 91 kan navngi 91 × 91 = 8281 ulike verdier, og 213 = 8192, så to tegn har alltid plass til 13 bit — med 89 verdier til overs. Det er hele trikset: 13 bit per 2 tegn er 6,5 bit per tegn, mot Base64s 6, og det gir omtrent 23 % overhead i stedet for 33 %.
Versjonen på 30 sekunder: test blir til fPNKd, og Hello, World! blir til >OwJh>}AQ;r@@Y?F. Dekoding er den nøyaktige omvendte operasjonen, og den krever det samme 91-tegnsalfabetet — et annet alfabet gir annen utdata fra de samme bytene.
Hvor 13- og 14-bitene kommer fra
91 × 91 = 8281 verdier kan navngis av et par tegn, noe som er mer enn 213 = 8192, men mindre enn 214 = 16384. Så et par tegn kan alltid bære 13 bit, og noen ganger 14. Koderen prøver først 13 bit: hvis 13-bitverdien er større enn 88, skriver den ut verdien som to tegn; ellers tar den en 14. bit og skriver ut den resulterende 14-bitverdien i stedet.
Grensen ved 88 er ikke vilkårlig. Den største verdien to tegn kan navngi er 90 + 91 × 90 = 8280, og 8192 + 89 = 8281 er allerede forbi den. Så ingen 14-bitgruppe kan noen gang ha et lavt 13-bitvindu på 89 eller mer, noe som betyr at dekoderen kan skille de to tilfellene ved å se på verdien alene:
| Hva dekoderen ser | Bit den bruker | Hvorfor |
| verdi & 8191 er 89 til 8191 | 13 bit | Verdier fra 89 og oppover kan bare komme fra 13-bit-grenen, fordi en 14-bitgruppe med et så høyt lavt 13-bitvindu måtte vært minst 8281 — som ingen par tegn kan navngi. |
| verdi & 8191 er 0 til 88 | 14 bit | Koderen faller bare tilbake til 14 bit når 13-bit-lesingen var 88 eller mindre, så denne grenen er reserveløsningen og ingenting annet. |
Det som er igjen til slutt — fra 1 til 13 bit — skrives ut som ett tegn, pluss et andre tegn når resten faktisk trengte mer enn 7 bit. Derfor vokser den kodede lengden i trinn på to tegn, og noen ganger slutter den på et oddetall.
Alfabetet, og de tre tegnene det dropper
Utskrivbar ASCII har 94 tegn, fra ! (0x21) til ~ (0x7E). Base91 bruker 91 av dem, og de tre den utelater er bindestreken -, apostrofen ' og skråstreken bakover \. Bokstaver, siffer og nesten all tegnsetting finnes i alfabetet nøyaktig én gang, i rekkefølgen som vises i tabellen over; det 92. til 94. utskrivbare tegnet er rett og slett ikke adresserbare.
Fordi alfabetet har en fast rekkefølge, er tegnet for en verdi et oppslag og ikke en formel. To implementasjoner som ordner alfabetet ulikt vil begge være «Base91» og ikke kunne lese hverandres utdata, som er den vanligste kilden til forvirrende resultater. Denne siden skriver ut alfabetet sitt, slik at utdataene alltid kan spores tilbake til det.
Base91 ved siden av de andre utskrivbare kodingene
| Koding | Bit per tegn | Størrelse mot inndataene | Merknader |
| Base16 (heks) | 4 | 200% | To tegn per byte, lett å lese, ingen alfabet å slå opp. |
| Base32 | 5 | 160% | Skiller ikke store og små bokstaver og er trygg å diktere for hånd, men den mest sløsende i gruppen. |
| Base58 | ~5,86 | ~137% | Valgt for adresser, ikke for tetthet: den unngår tegn som ser like ut. |
| Base64 | 6 | 133% | Standarden overalt: 4 tegn per 3 byte, med de 6 ubrukte bitene i det siste tegnet bortkastet. |
| Ascii85 / Base85 | 6,4 | 125% | 5 tegn per 4 byte, ingen oppslagstabell nødvendig, men den deler på 85 — se Ascii85-konverteren. |
| Base91 | ~6,5 | ~123% | Den tetteste av disse: 13 bit per 2 tegn, med en 14-bit-gruppe her og der. |
Prosentene er den asymptotiske kostnaden for hver koding, avrundet; de målte tegnantallene for én reell inndata på 92 byte står i tabellen lenger opp på denne siden. Base91 er nær det beste enhver koding kan gjøre med utskrivbar ASCII: 7 bit per tegn ville kreve 128 ulike tegn, som det utskrivbare området ikke kan levere.
Hva Base91 ikke er
- Ikke en standard. Det finnes ingen RFC. Referanseimplementasjonen er basE91 0.6.0 av Joachim Henke, utgitt under BSD 3-klausul-lisensen; "Base91" brukes også for alfabeter som ikke er dette.
- Ikke kryptering. Hvert tegn er en rett omforming av inndatabitene, og hvem som helst med alfabetet kan reversere den i ett trinn.
- Ikke URL-trygt. Alfabetet inneholder
#, %, &, /, ? og ", og alle endrer betydning i en URL, så Base91-utdata må prosentkodes før den settes i en spørringsstreng. - Ikke HTML-trygt. Det inneholder også
<, >, & og ", så en Base91-streng som settes inn i markup må escapes med HTML-entitetskonverteren. - Ikke fast lengde. Utdatalengden avhenger av bitmønsteret, ikke bare av antall byte, så to inndata av samme størrelse kan skrive ut ett tegn forskjellig.
Feller som faktisk biter
- Alfabetet på denne siden er referansen. Hvis et annet verktøy gir annen utdata for samme inndata, sammenlign alfabetet før man antar at en av sidene er ødelagt. De 91 tegnene må stå i samme rekkefølge.
- Ett feil tegn kan endre hele halen. Gruppegrensene bestemmes av verdiene som kom før, så en endring tidlig i strengen forskyver alt etter den, og halen dekodes bare med restbitene i den siste gruppen.
- Oddetall i utdatalengden er normalt. Det betyr ikke at strengen ble kuttet; den siste gruppen skriver ut ett tegn når restverdien får plass i 7 bit eller færre.
- Et publisert eksempel kan inneholde et linjeskift som ikke ble skrevet. En skallkommando som legger til et linjeskift er den vanlige grunnen til at en kjent Base91-verdi er ett tegn lengre enn den samme teksten gir her:
echo "Hello, World!" gir kodereren 14 byte og skriver ut >OwJh>}AQ;r@@Y?FF, mens de 13 bytene av teksten alene skriver ut >OwJh>}AQ;r@@Y?F. Begge er riktige, for ulike antall byte, og tallet under utdataboksen sier hvilken av dem man har. - Å dekode binære data som tekst fungerer ikke. Hvis de dekodede bytene ikke er gyldig UTF-8, finnes det ingen fornuftig tekst å vise; det er det heksadesimale utdatamodusen er til for.
Raske svar
“Hvorfor viser denne siden en verdi som er ett tegn forskjellig fra et annet Base91-verktøy?”
Nesten alltid et annet alfabet. Den nest vanligste årsaken er et verktøy som bare bruker 13-bit-grenen og aldri 14-bit-reserveløsningen; den varianten er mindre i kode, men gir annen utdata enn referansealgoritmen som brukes her.
Det finnes også ett eksakt tilfelle som kan avgjøres ved å telle byte, og det forklarer det mest siterte eksemplet av alle: et etterfølgende linjeskift. De fleste publiserte vektorer ble laget med en skallkommando, og skallet legger til linjeskiftet som avslutter linjen. De 13 bytene i Hello, World! skriver ut 16 tegn her, mens de 14 bytene i Hello, World! pluss et linjeskift skriver ut de 17 tegnene >OwJh>}AQ;r@@Y?FF. Lim inn en av verdiene i dekodingen: denne siden rapporterer antall byte, så de to lesingene kan skilles fra hverandre i stedet for å diskuteres. Knappen Eksempel laster den av de to som hører til leseren man bruker, og følger bryteren for koding/dekoding og velgeren Inndata er / Utdata som: tekstleseren får 16-tegnsverdien, heksleseren får 17-tegnsverdien med den etterfølgende 0A-byten synlig, og koderen får teksten som skal kodes i stedet for en Base91-streng.
“Er Base91 mindre enn Base64?”
Ja, med omtrent 8 % av den kodede størrelsen: 13 bit per 2 tegn mot 6 bit per tegn. På 92 byte tekst skriver Base64 ut 124 tegn, og Base91 skriver ut 114.
“Kan jeg dekode dette med en Base64-dekoder, eller omvendt?”
Nei. Alfabetene overlapper i bokstavene og sifrene, så en Base64-dekoder vil godta en Base91-streng som «gyldige» tegn og gi stille søppel. De er enige om ingenting annet enn formen på ordningen.
“Slutter utdataene med utfylling, slik Base64 gjør?”
Nei. Base91 har ikke noe utfyllingstegn i det hele tatt: restbitene til slutt skrives ut som den siste gruppen, så ingenting må legges til eller fjernes.
“Hvordan vet jeg at resultatet på denne siden er riktig?”
Trykk Selvtest 0 til 64 byte. Den koder og dekoder 130 bytemønstre som dekker hver lengde der 13- og 14-bit-delingen endrer seg, og sammenligner bytene som kommer tilbake med bytene som gikk inn. Verdiene på Eksempel-knappen krysssjekkes i tillegg mot en andre implementasjon skrevet for denne sidens testverktøy.
Standarder og kreditering
Denne siden implementerer algoritmen til basE91-referanseimplementasjonen (versjon 0.6.0) av Joachim Henke, distribuert under BSD 3-klausul-lisensen, med alfabetet skrevet ut over. Dekoding godtar og ignorerer mellomrom, slik referanseverktøyet gjør.
Sidens tekst er skrevet for dette nettstedet; algoritmen er ikke kopiert fra noe sted. Eksempelverdiene på Eksempel-knappen er det ene eksemplet som følger med referansepakken (merket «reference example») pluss verdier produsert av en andre, uavhengig implementasjon som ligger i denne sidens testverktøy (merket «cross-check»).