> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/fi/syvalliset-artikkelit/47-tex-tables-how-tex-calculates-spanned-column-widths.md).

# TeX-taulukot: miten TeX laskee usean sarakkeen levyydet

## Tämän artikkelin tavoitteena on

Tässä artikkelissa tutkimme, miten $$\mathrm\TeX$$ laskee taulukon sarakeleveydet, kun taulukoissa on useita sarakkeita kattavia merkintöjä (esim. taulukon otsikoita) (esim. käyttäen $$\mathrm\TeX$$ primitiiveistä `\omit` ja `\span`). Käyttäen yksinkertaista [”viitetaulukkoa”](#reference-table) lähtökohtana luomme joukon esimerkkejä — johdettuina tuosta viitetaulukosta — muuttamalla erilaisia merkintöjä siten, että saadaan useita sarakkeita kattavia sarakkeita. Tarkastelemalla näiden muutosten vaikutusta voimme alkaa muodostaa ymmärrystä taustalla olevasta algoritmista, jota $$\mathrm\TeX$$ käyttää katettujen sarakkeiden leveyksien laskemiseen.

### Käyttämällä $$\mathrm\TeX$$ sisällä $$\mathrm\LaTeX$$

Tarkastellaksemme ja selittääksemme *miten* $$\mathrm\TeX$$ päättää katettujen sarakkeiden leveydet, on tarpeen sivuuttaa kaikki ihanat $$\mathrm\LaTeX$$ taulukkopaketit ja palata perustavanlaatuisiin, matalan tason (primitiivisiin) taulukonluontikomentoihin: erityisesti `\\halign{...}`, `\span` ja `\omit`. [Olemassa olevat $$\mathrm\TeX$$/$$\mathrm\LaTeX$$ taulukkopaketit](https://ctan.org/topic/table) ovat tietenkin olennaisia tuottavuustyökaluja ja tarjoavat runsaasti erittäin hyödyllisiä toimintoja, joiden avulla käyttäjät voivat nopeasti tuottaa valtavan valikoiman taulukkomateriaalia käyttäen $$\mathrm\LaTeX$$. Nuo paketit tarjoavat olennaisen ”makrokuorrutuksen”, joka on rakennettu $$\mathrm\TeX$$’n matalan tason käyttäytymisen ympärille, ja niiden kehittäjät tarjoavat erittäin tervetulleita abstraaktioita ja eristyskerroksia, jotka huolehtivat taustalla olevista monimutkaisuuksista. Monet noista paketeista ovat todella uskomattomia monimutkaisen $$\mathrm\TeX$$ ohjelmoinnin taidonnäytteitä: meidän kaikkien pitäisi olla kiitollisia siitä, että ne ovat olemassa suojaamassa meitä siltä, että joudumme käyttämään raakaa $$\mathrm\TeX$$!

Varsinainen algoritmi, jota $$\mathrm\TeX$$ käyttää katettujen sarakkeiden leveyksien laskemiseen, selitetään sivulla 245 [$$\mathrm\TeX\text{book}$$](https://www.amazon.co.uk/TeXbook-Donald-E-Knuth/dp/0201134489) ja lisätiedoilla luvussa 801 (s. 336) painetussa kirjassa, joka sisältää $$\mathrm\TeX$$’n lähdekoodin [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373). Kuitenkin monille ihmisille (itseni mukaan lukien) Knuthin selitykset ovat ajoittain varsin tiiviitä ja napakoita, ja toisinaan niitä voi olla vaikea seurata yksityiskohtaisesti: havainnollistetut esimerkit ovat aina erittäin hyödyllisiä.

### Kyllä, taulukot ovat monimutkaisia

Luvussa 768 (s. 322) kirjassa [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373), Knuth tekee mielenkiintoisen huomautuksen:

> ”Se on tavallaan ihme aina, kun `\halign` ja `\valign` toimii, koska ne kulkevat niin monen $$\mathrm\TeX$$.”

Lisäksi neliosaisen kirjasarjan osa IV [$$\mathrm\TeX\text{ in Practice}$$](https://www.amazon.co.uk/Tex-Practice-Set-Stephan-Bechtolsheim/dp/038797296X/ref=sr_1_11?s=books\&ie=UTF8\&qid=1504256043\&sr=1-11\&keywords=TeX+in+Practice) omistaa peräti 180 sivua (s. 199–379) taulukoiden luomiseen $$\mathrm\TeX$$ kautta `\halign` ja `\valign`.

Siispä on turvallista todeta $$\mathrm\TeX$$ että taulukot ovat todellakin ”melko hankalia”.

### Sarakkeiden kattaminen: \\\omit, \\\span ja \\\multispan

Kuten todettu, jotta voimme tutkia $$\mathrm\TeX$$’n sarakeleveiden laskentaa meidän täytyy käyttää ”raakaa” $$\mathrm\TeX$$; tällä tarkoitetaan yhdistelmää primitiivikomentoja ja yhtä $$\text{Plain }\mathrm\TeX$$ makroa nimeltä `\\multispan`. Vaikka emme aio käyttää näitä komentoja suoraan esimerkkitaulukoidemme havainnollistamiseen (eli selittää täysin kaikki $$\mathrm\TeX$$ koodi), on syytä lisätä niistä lyhyt huomautus:

* `\halign`: Yksi kahdesta $$\mathrm\TeX$$ primitiivistä (komennoista) taulukoiden luomiseen. Toinen on `\valign` mutta sitä ei käytetä yhtä laajalti, eikä siitä keskustella tässä artikkelissa.
* `\omit`: A $$\mathrm\TeX$$ primitiivi (komento), joka käskee $$\mathrm\TeX$$ sivuuttamaan taulukkomerkinnän preambulumallin.
* `\span`: A $$\mathrm\TeX$$ primitiivi (komento), jota käytetään kahden vierekkäisen taulukkomerkinnän yhdistämiseen.
* `\\multispan{n}`: Tavallinen $$\mathrm\TeX$$ makro, jolla katetaan `n` saraketta.

Pohjimmiltaan sarakkeita katettaessa $$\mathrm\TeX$$ ohitetaan sopiva määrä taulukon preambulumalleja ja yhdistetään tarvittava määrä taulukkomerkintöjä yhdeksi merkinnäksi. `\\multispan{n}` toimii laajenemalla sarjaksi `\omit` ja `\span` tokeneita, joita tarvitaan kattamaan `n` saraketta. Esimerkiksi `\\multispan{3}` laajenee muotoon `\\omit\\span\\omit\\span\\omit`.

## Viitetaulukkomme esittely

Tässä on viitetaulukkomme ja sen jälkeen huomioitu versio, joka selittää sen rakentamisessa käytetyt osat:

![{{{alt}}}](/files/0e38cacec94cfdf089a446780d386aa063ee0f56)

Muokkaamalla viitetaulukkoamme havaitsemme, mitä taulukon leveydelle ja yksittäisten sarakkeiden leveydelle tapahtuu, kun lisäämme merkintöjä, jotka kattavat useita sarakkeita. Tämä viitetaulukko tuotettiin raakana $$\mathrm\TeX$$ käyttäen `\\halign{...}` primitiiviä yhdessä useiden mukautettujen makrojen kanssa, joita tarvitaan taulukoiden ladontaan — emme käsittele noita makroja, koska ne eivät ole olennaisia esimerkkien ja selitysten ymmärtämiseksi.

Tässä on huomioitu versio viitetaulukostamme, joka selittää sen ominaisuudet:

![{{{alt}}}](/files/452ed61b50062153f422e30c9aa06998a3cea5b6)

Ensimmäisessä esimerkkitaulukkoryhmässämme ja alkuperäisessä viitetaulukossa on kaikissa asetettuna `\\tabskip=0pt` jotta $$\mathrm\TeX$$ ei lisää mitään väliä sarakkeidemme väliin: käytännössä ne kaikki koskettavat toisiaan. Syy tähän on yksinkertaistaa alkuperäistä keskustelua ja sitä seuraavia laskelmia — myöhemmin artikkelissa tuomme takaisin nollasta poikkeavan `\tabskip` liiman tutkiaksemme sen vaikutusta katettujen sarakkeiden leveyksien laskemiseen.

Kuten huomautuksissa todetaan, olemme lisänneet hieman tyhjää tilaa (5pt) kaikkien ei-kattavien taulukkomerkintöjen alkuun (lukuun ottamatta ensimmäistä riviä). Tämä 5pt:n tyhjä tila on osa kaikkien ei-kattavien merkintöjen (lukuun ottamatta ensimmäistä riviä) kokonaisleveyttä, ja se lisättiin vain, jotta taulukko näyttäisi hieman vähemmän sekavalta.

### Lyhyt huomautus taulukon leveydestä

Se `\\halign{...}` komennolla on kolme muotoa:

* `\\halign{...}`: aseta taulukon leveydeksi se, minkä $$\mathrm\TeX$$ laskee merkintöjen koon (ja `\tabskip` liiman) perusteella;
* `\\halign to *width* {...}`: käske $$\mathrm\TeX$$ ladontamaan taulukko määritettyyn `*leveyteen*`;
* `\\halign spread *amount*{...}`: säädä laskettua leveyttä `*määrällä*`.

Kun $$\mathrm\TeX$$ ladontaa taulukon käyttäen `\\halign{...}` sen täytyy lukea koko taulukko muistiin suorittaakseen erilaiset laskelmat, joita tarvitaan sen ladontaan. Siksi, ellei leveyttä ole määritetty käyttämällä `\\halign to *width* {...}` et voi tietää lopullista leveyttä ennen kuin $$\mathrm\TeX$$ on saanut sen käsittelyn (ladonnan) valmiiksi. Yksi tapa saada `\\halign{...}` tuottaman taulukon leveys on ensin ladontaa taulukko `\vbox{...}` (esim. `\\setbox0=\\vbox{\\halign{...}}`) ja sitten esimerkiksi käyttää `\\the\\wd0` leveuden saamiseksi.

### Ei automaattista rivinvaihtoa taulukkomerkinnöissä

On tärkeää huomata, että kun $$\mathrm\TeX$$ ladotaan taulukkoa, joka on luotu käyttäen `\\halign{...}` taulukkomerkintöjen sisällä oleva teksti ei automaattisesti joudu rivinvaihdon alaiseksi: taulukkomerkinnät ladotaan *rajoitetussa vaakatilassa*— aivan kuten `\hbox`. Rivinvaihdon mahdollistamiseksi taulukkomerkinnän tekstin täytyy olla suljettuna `\vbox{...}` yhdessä sopivan arvon käyttämisen kanssa `\hsize` sisällä tuossa `\vbox{...}`. Huomaa kuitenkin, että teksti sisällä `\\noalign{...}` komennossa ( $$\mathrm\TeX$$ primitiivi), jota käytetään `\\halign{...}` ei ole alttiina $$\mathrm\TeX$$’n rivinvaihdolle. Käytännössä, ja kuten sen nimi vihjaa, `\\noalign{...}` sallii $$\mathrm\TeX$$ ”karata” `\\halign{...}` ja sijoittaa aineistoa taulukon rivien väliin — tyypillisesti vaakaviivojen tuottamiseksi taulukon rivien väliin.

### Ei sallittu: \\\halign{...} sisällä \\\hbox{...}

Et voi *suoraan* ladota `\\halign{...}` sisällä `\hbox{...}`. Yrittäessäsi käyttää `\\hbox{\\halign{...}}` tuottaa melko hämmentävän virheen:

```latex
! Puuttuva } lisätty.
<inserted text>
                }
<luetaan uudelleen>
                   \halign
r.1 \\hbox{\\halign
```

#### Selitys tälle virheelle

Sulkevan `\hbox{...}` $$\mathrm\TeX$$ sisäisen *rajoitetussa vaakatilassa*takia `\\halign{...}` on *vertikaalisen tilan* komento. Esimerkiksi, jos käytät `\\halign{...}` keskellä kappaletta, $$\mathrm\TeX$$ lopettaa kappaleen, käsittelee `\\halign{...}` ja jatkaa sitten kappaleen loppuosalla.

Kun käytetään sisällä `\hbox{...}`, `\\halign{...}` laukaisee $$\mathrm\TeX$$ yrittämään paluuta vertikaaliseen tilaan pakottamalla nykyisen ryhmän sulkeutumaan: $$\mathrm\TeX$$ ilmoittaa ”`! Puuttuva }`” ja antaa virheen, koska se luulee sinun tehneen virheen ryhmittelyn käytössä. Vaikka oikea aaltosulje (`}`) ei ehkä puutu sinun $$\mathrm\TeX$$ koodistasi, virheilmoitus on oire siitä, että `\hbox{...}` ”tulee tielle” ja $$\mathrm\TeX$$ tekee ”parhaan arvauksensa” sopivasta toimintatavasta ongelman ratkaisemiseksi.

## Esimerkkejä taulukoista, joissa on useita sarakkeita kattavia sarakkeita

Seuraava taulukografiikoiden sarja tarjoaa joukon esimerkkejä havainnollistamaan taulukon sarakkeiden kattamisen vaikutusta: se osoittaa, että pitkät taulukkomerkinnät voivat aiheuttaa odottamattomia tuloksia tiettyjen sarakkeiden leveyteen — ja näin ollen itse taulukon leveyteen. Kysymys, johon aiomme vastata, on mitä $$\mathrm\TeX$$ tekee, kun jokin taulukkomerkintä kattaa useita sarakkeita, mutta on ”liian leveä mahtuakseen”. Kuten edellä todettiin, $$\mathrm\TeX$$ soveltaa todella tiettyä algoritmia tähän sarakeleveyksien laskemisongelmaan: seuraavien esimerkkien tarkoituksena on auttaa kehittämään ”tuntumaa” tuon algoritmin toimintaan.

### Esimerkkitaulukko 1

Tässä esimerkissä käytämme `\\multispan{2}` kattamaan sarakkeet 1 ja 2 merkinnällä, jonka teksti on **Taulukon otsikko**:

![{{{alt}}}](/files/0a6002e882fd492ab5d59eb8a67e02bdfb2fcefb)

#### Havainnot

* Tämän taulukon leveys on sama kuin [viitetaulukon](#reference-table): $$327.71722\text{pt}$$.
* Sarakkeet 1 ja 2 kattavan merkinnän leveys on $$81.04953\text{pt}$$ mikä on pienempi kuin niiden sarakkeiden merkintöjen kokonaisleveys, joita se kattaa: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$

## Esimerkkitaulukko 2

Kuten [Esimerkkitaulukko 1](#example-table-1), tässäkin esimerkissä käytetään `\\multispan{2}` kattamaan sarakkeet 1 ja 2, mutta tässä käytämme pidempää merkintää, jonka teksti on **Hieman pidempi taulukon otsikko**.

![{{{alt}}}](/files/8c7d9cafaf7d1148186e9e98de6ed23f0825af31)

#### Havainnot

Jos vertaat tätä esimerkkiä meidän [viitetaulukon](#reference-table) nähdään seuraavaa:

* Tämän taulukon leveys on kasvanut $$327.71722\text{pt}$$ kohteeseen $$374.37032\text{pt}$$: yhteensä $$46.6531\text{pt}$$.
* Sarakkeet 1 ja 2 kattavan merkinnän ($$156.28664\text{pt}$$) leveys on suurempi kuin niiden sarakkeiden merkintöjen kokonaisleveys, joita se kattaa: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$. Tämä ero on $$156.28664\text{pt}-109.63355\text{pt} = 46.6531\text{pt}$$ mikä on sama määrä, jolla taulukon leveys on kasvanut.
* $$\mathrm\TeX$$ on säätänyt sarakkeen 2 leveyttä tarjotakseen tarvittavan lisätilan. Myöhemmin $$\mathrm\TeX$$ laskee sen määrän, jolla sarakkeen 2 täytyy kasvaa.
* Sarake 1 ei muutu: sen leveys ei ole muuttunut sarakkeet 1 ja 2 kattavan merkinnän vuoksi.

### Esimerkkitaulukko 3

Tässä esimerkissä käytämme `\\multispan{3}` kattamaan sarakkeet 1–3 merkinnällä, jonka teksti on sama kuin [Esimerkkitaulukko 2](#example-table-2): **Hieman pidempi taulukon otsikko**.

![{{{alt}}}](/files/23905028202168d38bf5570b088946ee2543e1e5)

#### Havainnot

* Tämän taulukon leveys on sama kuin [viitetaulukon](#reference-table): $$327.71722\text{pt}$$.
* Sarakkeet 1–3 kattavan merkinnän ($$156.28664\text{pt}$$) leveys on pienempi kuin niiden kolmen sarakkeen merkintöjen kokonaisleveys, joita se kattaa: $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Yksikään sarakeleveydestä ei ole muuttunut sarakkeet 1–3 kattavan merkinnän vuoksi.

Alatko nähdä muodostuvan kuvion?

### Esimerkkitaulukko 4

Kuten [Esimerkkitaulukko 3](#example-table-3), tässä käytämme `\\multispan{3}` kattamaan sarakkeet 1–3, mutta tällä kertaa merkinnällä, jonka teksti on huomattavasti pidempi: **Huomattavasti pidempi taulukon otsikko, joka ulottuu pitkälle**.

![{{{alt}}}](/files/77723fe0fd730a88199ade6618d387a8653fad84)

#### Havainnot

* Verrattuna [viitetaulukon](#reference-table), tämän taulukon leveys on kasvanut $$327.71722\text{pt}$$ kohteeseen $$465.95685\text{pt}$$: kasvu on $$138.23963\text{pt}$$.
* Sarakkeet 1–3 kattavan merkinnän leveys on $$306.91216\text{pt}$$.
* Kolmen katetun sarakkeen merkintöjen kokonaisleveys on $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Pitkän kattavan merkinnän ja sarakkeiden 1–3 merkintöjen välinen leveusero on $$306.91216\text{pt}-168.67254\text{pt}=138.23962\text{pt}$$. Sama määrä (neljän desimaalin tarkkuudella!), jolla taulukon leveys on kasvanut.
* Vain sarakkeen 3 leveyttä on kasvatettu: sarake 1 eikä sarake 2 ole muuttunut.

#### Kuvio muodostuu

Jos katsomme [Esimerkkitaulukko 2](#example-table-2) ja [Esimerkkitaulukko 4](#example-table-4) voimme nähdä, että molemmissa tapauksissa kyseessä on **kattamisen viimeinen sarake** jonka leveyttä kasvatettiin, jotta saatiin tilaa pitkälle merkinnälle, joka kattoi sarakkeet:

* On [Esimerkkitaulukko 2](#example-table-2): Pitkä merkintä kattoi sarakkeet 1 ja 2. Sarake 2 ”venyi”.
* On [Esimerkkitaulukko 4](#example-table-4): Pitkä merkintä kattoi sarakkeet 1–3. Sarake 3 ”venyi”.

#### Sarakkeen 3 leveys: Nouseeko algoritmi esiin?

Seuraavat laskelmat antavat selkeämmän kuvan siitä, mitä $$\mathrm\TeX$$ tekee. Tässä on se, mitä tiedämme:

* Sarakkeet 1–3 kattavan pitkän merkinnän leveys on $$306.91216\text{pt}$$.
* Sarakkeiden 1 ja 2 merkintöjen kokonaisleveys on $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$.

Mikä on näiden arvojen välinen erotus? Se on $$306.91216\text{pt}-109.63355\text{pt} = 197.2786\text{pt}$$ ja tämä on sarakkeelle 3 käytetty leveys: se syntyy suoraan $$\mathrm\TeX$$.

### Esimerkkitaulukko 5

Ennen kuin siirrymme monimutkaisempaan esimerkkiin, tässä on vielä yksi ”yksinkertainen” esimerkki. Tämä taulukko sisältää saman pitkän merkinnän kuin [Esimerkkitaulukko 4](#example-table-4): **Huomattavasti pidempi taulukon otsikko, joka ulottuu pitkälle**; kuitenkin tällä kertaa käytämme `\\multispan{6}` mikä sallii kyseisen merkinnän kattaa koko taulukon. Kuten näet, tuloksena oleva taulukko on edelleen samanlevyinen kuin meidän [viitetaulukon](#reference-table) ($$327.71722\text{pt}$$) mikä tarkoittaa, ettei yksikään sarake ole muuttunut tämän hyvin pitkän merkinnän vuoksi. Selvää on, että tämä johtuu siitä, että merkinnän leveys ($$306.91216\text{pt}$$) on pienempi kuin kaikkien niiden merkintöjen kokonaisleveys, joita se kattaa: $$327.71722\text{pt}$$; toisin sanoen taulukon leveys.

![{{{alt}}}](/files/a0aa24d29dd42ea451c0b569514e0459dee3f1fd)

### Esimerkkitaulukko 6: Hieman monimutkaisempi

Tässä tarkastelemme kolmen esimerkkitaulukon sarjaa (6(a)–6(c)) näyttääksemme kahden eri merkinnän vaikutuksen, jotka molemmat ulottuvat sarakkeeseen 5. [Esimerkkitaulukko 6(a)](#example-table-6a) ja [Esimerkkitaulukko 6(b)](#example-table-6b) kumpikin näyttää taulukon, jossa on yksi merkintä, joka kattaa useita sarakkeita sarakkeeseen 5 asti. [Esimerkkitaulukko 6(c)](#example-table-6c) yhdistää molemmat kattavat merkinnät yhdeksi taulukoksi ja esittää kysymyksen: mikä merkintä itse asiassa määrittää sarakkeen 5 leveyden, ja miksi? Vastaus vie meidät $$\mathrm\TeX$$.

#### Esimerkkitaulukko 6(a)

![{{{alt}}}](/files/3218052953deafc8169c22b0e8f32a6c72bd1364)

**Havainnot**

* Verrattuna [viitetaulukon](#reference-table), tämän taulukon leveys on kasvanut $$327.71722\text{pt}$$ kohteeseen $$371.11153\text{pt}$$: kasvu on $$43.39431\text{pt}$$.
* Sarakkeet 3–5 kattavan merkinnän leveys on $$215.06683\text{pt}$$.
* Sarakkeiden 3–5 merkintöjen kokonaisleveys on $$59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 171.67253\text{pt}$$.
* Sarakkeiden 3–5 kattamien merkintöjen ja kattavan merkinnän leveyden välinen erotus on $$215.06683\text{pt}-171.67253\text{pt}=43.3943\text{pt}$$: täsmällinen määrä (neljän desimaalin tarkkuudella!), jolla taulukon leveys on kasvanut .

#### Esimerkkitaulukko 6(b)

![{{{alt}}}](/files/d37cae8c540df4c3dd9b0b90a63a2269dee49b2f)

**Havainnot**

* Verrattuna [viitetaulukon](#reference-table), tämän taulukon leveys on kasvanut $$327.71722\text{pt}$$ kohteeseen $$353.3233\text{pt}$$: kasvu on $$25.60608\text{pt}$$.
* Sarakkeet 1–5 kattavan merkinnän leveys on $$306.91216\text{pt}$$.
* Sarakkeiden 1–5 merkintöjen kokonaisleveys on $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 281.30608\text{pt}$$.
* Sarakkeiden 1–5 kattamien merkintöjen ja kattavan merkinnän leveyden välinen erotus on $$306.91216\text{pt}-281.30608\text{pt}=25.60608\text{pt}$$: **note** tämä on *pienempi* kuin arvo, joka laskettiin kohdassa [Esimerkki 6(a)](#example-table-6a), joka oli $$43.3943\text{pt}$$.

#### Esimerkkitaulukko 6(c)

Tässä yhdistämme esimerkkitaulukoiden [6(a)](#example-table-6a) ja [6(b)](#example-table-6b) merkinnät yhdeksi taulukoksi: mitä tapahtuu?

![{{{alt}}}](/files/86da1ff422d48b3303429c74fbdf303ce89345e1)

**Havainto**

* Verrattuna [viitetaulukon](#reference-table), tämän taulukon leveys on kasvanut $$327.71722\text{pt}$$ kohteeseen $$371.11153\text{pt}$$: kasvu on $$43.39431\text{pt}$$. Huomaamme, että tämä on täsmälleen sama kuin [Esimerkkitaulukko 6(a)](#example-table-6a).

#### Mitä $$\mathrm\TeX$$ tekee?

Ymmärtääksemme $$\mathrm\TeX$$’n algoritmin ja päätöksentekoprosessit, huomaamme että tämä merkintä

![{{{alt}}}](/files/d09fde8ea683b0c012e56b8156a2186d552a9b1b)

ulottuu pidemmälle kuin merkinnät, joita $$25.60608\text{pt}$$kattaa; kuitenkin tämä merkintä

![{{{alt}}}](/files/a140b3a4bd9897f9b92867b5da5de8da7c967d5c)

ulottuu vielä pidemmälle kuin katetut merkinnät: määrällä $$43.3943\text{pt}$$. Siksi kyseinen merkintä ”voittaa kilpailun” ja sarakkeen 5 leveyttä kasvatetaan **maksimin** näistä kahdesta arvosta ($$43.3943\text{pt}$$). Sarakkeen 5 leveys muuttuu nyt $$59.6501\text{pt} + 43.3943\text{pt} = 103.0444\text{pt}$$ sopimaan merkinnän kanssa, joka kattaa sarakkeet 3–5. Kuvaustamme tapahtumien tarkasta ”kulusta” on hieman yksinkertaistettu, mutta lopputulos on kuten olemme kuvanneet.

## Tuodaan takaisin hieman monimutkaisuutta

Jotta keskustelumme monimutkaisuus pysyisi mahdollisimman pienenä (toistaiseksi), olemme käyttäneet suhteellisen yksinkertaisia esimerkkejä havainnollistamaan $$\mathrm\TeX$$’n algoritmin periaatteita; erityisesti asetimme `\\tabskip=0pt`. Käytännössä ”todellisen maailman” taulukoissa on todennäköisesti paljon merkintöjä, jotka kattavat joukon sarakkeita, ja tietenkin niissä on nollasta poikkeavat arvot `\tabskip` liimalle — aiheeseen palaamme nyt.

### \\\tabskip-liima ja katettujen sarakkeiden leveydet

Taulukon suunnittelu vaatii usein tyhjän tilan lisäämistä sarakkeiden väliin, ja tietenkin $$\mathrm\TeX$$ tarjoaa tämän mahdollisuuden primitiivikomennolla nimeltä `\tabskip`. Tätä komentoa voidaan käyttää lisäämään kiinteää tai joustavaa liimaa (väliä):

* taulukon ennen (eli sarakkeen 1 vasemmalle puolelle);
* yhden tai useamman sarakkeen väliin;
* taulukon jälkeen (eli viimeisen sarakkeen oikealle puolelle).

Tässä esimerkki muistutukseksi:

![{{{alt}}}](/files/3e1df5ccf639508e60231260a4c797ad6a081882)

### Miten \\\tabskip-liima vaikuttaa katettujen sarakkeiden leveyksiin?

Nollasta poikkeavan `\tabskip` liiman olemassaolo sarakkeiden välissä tarjoaa lisätilaa, jonka katetut merkinnät voivat ”imeä” ennen kuin $$\mathrm\TeX$$ joutuu miettimään katetun alueen viimeisen sarakkeen leveyden kasvattamista.

Seuraavassa esimerkissä käytämme kahta taulukkoa vertaillaksemme kahden sarakkeen kattamisen tuloksia. Ainoa ero taulukoiden välillä on `\tabskip` liiman käyttö.

* Ensimmäisessä esimerkissä käytämme alkuperäistä ”viitetaulukkoamme”, jossa, kuten muistat, on asetettuna `\\tabskip=0pt`.
* Toisessa esimerkissä käytetään muokattua versiota meidän [viitetaulukon](#reference-table) (kommentoitu edellä), jossa on `\\tabskip=10pt` ennen taulukkoa ja sen jälkeen, mutta mikä tärkeämpää, siinä on asetettuna `\\tabskip=20pt` sarakkeiden väliin.

Sisällä *muokatun* viitetaulukon kaksi katettua saraketta eivät vaikuta sarakeleveyksiin (eivätkä taulukon leveyteen), mutta ne vaikuttavat sarakkeen 2 leveyteen (ja taulukon leveyteen) *alkuperäisessä* [viitetaulukon](#reference-table).

### Alkuperäinen viitetaulukko: \\\tabskip=0pt

Tässä näytämme alkuperäisen [viitetaulukon](#reference-table) yhdessä toisen taulukon kanssa (johdettu alkuperäisestä [viitetaulukon](#reference-table)) jossa on merkintä ”**Testaa pidempi taulukon otsikko**” joka kattaa sarakkeet 1 ja 2. On täysin selvää, että sarake 2 (kuvion toisessa taulukossa) ja siten koko taulukko, molemmat muuttuvat katettujen sarakkeiden vaikutuksesta.

![{{{alt}}}](/files/3cf6a38c443ec94e9fe488b357377ffb46de55e5)

### Muokattu viitetaulukko: \\\tabskip=20pt

Tässä näytämme muokatun viitetaulukkomme yhdessä toisen taulukon kanssa (johdettu muokatusta viitetaulukostamme), jossa on myös merkintä ”**Testaa pidempi taulukon otsikko**” joka kattaa sarakkeet 1 ja 2. On täysin selvää, että kuvion toisessa taulukossa sarakkeen 2 leveys tai taulukon leveys eivät muutu katettujen sarakkeiden vaikutuksesta. Tässä tapauksessa `\tabskip` liiman (`20pt`) olemassaolo sarakkeiden välissä on auttanut ”imeyttämään” merkinnän tekstin vaatimaan tilan, kun se kattaa sarakkeet 1 ja 2:

![{{{alt}}}](/files/5b50a8507594830fd2b423682f21fa9e0388910b)

## Ydin $$\mathrm\TeX$$’n algoritmista

Toivottavasti yllä esitetyt esimerkit ovat auttaneet kehittämään ”tuntumaa” siihen, mitä $$\mathrm\TeX$$ tekee katettujen merkintöjen sovittamiseksi ja miten $$\mathrm\TeX$$ säätelee tarvittaessa **viimeisen** sarakkeen leveyttä kunkin katettujen sarakkeiden alueen sisällä. Yksittäisten sarakkeiden merkintöjen leveyden lisäksi nollasta poikkeavan `\tabskip` liiman olemassaolo on tärkeä tekijä, jonka $$\mathrm\TeX$$ ottaa huomioon päättäessään, tarvitseeko sen säätää mitään sarakeleveyksiä. Keskeinen muistettava asia on, että $$\mathrm\TeX$$’n tavoitteena on laskea sopiva leveys **viimeinen sarake** kunkin laajennettujen sarakkeiden alueen sisällä.

### Lopullinen taulukkoesimerkki: viimeiset sarakkeet laajennetulla alueella

Tässä viimeisessä esimerkissä käytämme jälleen muokattua viitetaulukkoa (jossa `\tabskip` edellä käsitellyt liima-arvot) saadaksemme toisen taulukon, joka sisältää useita sääntöjen kattamia sarakkeita — olemme käyttäneet sääntöjä, jotta laajennukset olisi helpompi nähdä.

Kaksi taulukkoa on kohdistettu huolellisesti osoittamaan, että ylemmässä taulukossa yksikään ennen saraketta 5 oleva sarake ei ole muuttunut laajennettujen sarakkeiden vuoksi. Kaavion vasemmalla puolella oleva tummempi vihreä alue osoittaa, että molempien taulukoiden sarakkeet 1–4 ovat edelleen täysin kohdakkain. Oikealla on vaaleamman vihreä varjostettu alue, joka osoittaa, että vain sarakkeisiin 5 ja 6 ovat vaikuttaneet laajennetut merkinnät.

Ylemmässä taulukossa laajennukset ovat seuraavat:

* sarakkeet 1–5: kattavana on $$400\text{pt}$$ sääntö;
* sarakkeet 3–5: kattavana on $$200\text{pt}$$ sääntö;
* sarakkeet 4–6: kattavana on $$250\text{pt}$$ sääntö.

![{{{alt}}}](/files/d9addc268711b21d46c2573d47ec51bc59797363)

Selitys on jälleen se, että laajennettujen sarakkeiden sarjassa vain viimeisen sarakkeen leveyttä säädetään (tarvittaessa): välissä oleviin sarakkeisiin ei vaikuteta, ja tässä se tarkoittaa sarakkeita 1–4 — tosin tietenkin sarakkeiden 1–4 leveydet (ja välissä oleva `\tabskip` liima) otetaan huomioon laskettaessa sarakkeiden 5 ja 6 säädettyjä leveyksiä.

### Käynti läpi $$\mathrm\TeX$$’n algoritmista

Päätämme *yksinkertaistettu* läpikäyntiä “$$\mathrm\TeX$$ajatteluprosesseista” sen laskiessa sarakkeiden leveyksiä laajennetuissa merkinnöissä. Kuvailla $$\mathrm\TeX$$sen algoritmien kuvaaminen ei ole aina suoraviivaista, joten käytämme hieman “yksinkertaistavaa taiteellista vapautta” antaaksemme yleiskuvan siitä, mitä tapahtuu. Lukijat, joita kiinnostavat kaikki sotkuiset yksityiskohdat, voivat katsoa painetun kirjan luvun 801 (sivu 336), joka sisältää $$\mathrm\TeX$$’n lähdekoodin [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373).

Todelliset taulukot luodaan usein käyttämällä runsaasti `\span` primitiiviä (esim. sisällä $$\mathrm\LaTeX$$ paketeissa) taulukon sisälle useita laajennettujen sarakkeiden esiintymiä varten. Tämän hallitsemiseksi tietorakenteet (syvällä $$\mathrm\TeX$$) ylläpitävät tietoja (ns. *laajennussolmut*) jotka kertovat $$\mathrm\TeX$$ taulukon merkintöjen/sarakkeiden välisistä yhteyksistä (laajennuksista). Selvää on, että $$\mathrm\TeX$$ on sovellettava algoritmejaan järjestelmällisesti ja sen on käsiteltävä koko taulukko lopullisten laskelmiensa tekemiseksi — määrittääkseen kaikkien sarakkeiden leveydet, taulukon kokonaisleveyden ja tarvittaessa sen määrän, jolla taulukossa käytettyjen joustavien liimojen on venyttävä tai kutistuttava. Ei ole oikeastaan yllättävää, että $$\mathrm\TeX$$ ei voi kertoa lopullista taulukon leveyttä ennen kuin se on täysin käsitellyt `\\halign{...}` komennon — sillä sillä todella on paljon tehtävää!

Sarakkeiden leveyksien laskennan lähtökohta on sarake 1, koska tietenkään mikään ei voi ulottua vasemmalta puolelta (eikä *yli/sisään*) sarakkeeseen 1. $$\mathrm\TeX$$ aloittaa määrittämällä sarakkeen 1 leveyden selvittämällä, mikä merkintä, jolla on suurin *luonnollinen leveys*. Kutsutaan tätä enimmäisleveyttä $$w\_1$$ja jos on merkintöjä, jotka ulottuvat sarakkeesta 1 sarakkeeseen 2, kutsutaan kyseisen merkinnän leveyttä $$w\_{12}$$ (leveys 1:stä 2:een). Lisäksi merkitsemme `\tabskip` sarakkeiden 1 ja 2 välisen liiman $$t\_{1}$$—huomaa, että tarkastelemme vain *luonnollinen leveys* sen `\tabskip` liiman osuutta ja jätämme toistaiseksi huomiotta mahdolliset venymä- tai kutistumiskomponentit, joita sillä saattaa olla. Olkoon myös kaikkien sarakkeessa 2 olevien ei-laajennettujen merkintöjen suurin luonnollinen leveys $$w\_2$$.

Keskeinen huomio on, että $$\mathrm\TeX$$ yrittää laskea sarakkeen 2 leveyden tarkastelemalla vain niitä merkintöjä, joissa laajennus *alkaa* sarakkeesta 1 ja *päättyy* sarakkeeseen 2. Keskeinen huomioon otettava asia $$\mathrm\TeX$$ on testi $$\max(w\_{2}, w\_{12} - (w\_1+ t\_1))$$—sarakkeiden 1 ja 2 yli voi ulottua useita merkintöjä: jotkut voivat olla kapeita (pieni $$w\_{12}$$), toiset hyvin leveitä (suuri $$w\_{12}$$) joten $$\mathrm\TeX$$ etsii sitä, jolla on suurin vaikutus (siis $$\max(\text{...})$$). Tässä $$w\_{12} -(w\_1+ t\_1)$$ on määrä, jolla sarakkeiden 1 ja 2 yli ulottuva merkintä “vuotaa yli” sarakkeesta 1 sarakkeeseen 2: huomaa, että $$\mathrm\TeX$$ käyttää sarakkeen 1 leveyttä **ja** sivustolta `\tabskip` liiman ($$t\_{1}$$) sarakkeiden 1 ja 2 välillä. Kun $$\mathrm\TeX$$ on selvittänyt, vaikuttavatko jotkin sarakkeesta 1 2:een ulottuvat laajennukset todella sarakkeen 2 leveyteen, se asettaa sarakkeen 2 leveydeksi suurimman määrittämänsä arvon (kuvattua testiä käyttäen). $$\mathrm\TeX$$ jatkaa muiden sarakkeiden läpikäymistä suorittaen vastaavia testejä.

Ja lopuksi, täydellisyyden vuoksi, lainaamme tässä ytimen $$\mathrm\TeX$$sarakkeiden leveyksien laskenta-algoritmista (otettu Knuthin lähdekoodidokumentaatiosta $$\mathrm\TeX$$):

Olkoon $$w\_{ij}$$ kaikkien niiden merkintöjen luonnollisten leveyksien maksimi, jotka ulottuvat sarakkeiden $$i$$ läpi $$j$$, mukaan lukien. Lopulliset sarakeleveydet määritellään kaavalla

$$\begin{equation\*} w\_j=\max\_{1\leq i\leq j}\biggl(w\_{ij}-\sum\_{i\leq k< j}(t\_k+w\_k)\biggr) \end{equation\*}$$

jossa $$t\_k$$ on sarakkeiden välisen tabskip-liiman luonnollinen leveys $$k$$ ja $$k+1$$.

## Loppuhuomautus: Overleafin käyttäminen taulukoiden tuottamiseen SVG-grafiikkana

Kaikki $$\mathrm\TeX$$ tässä artikkelissa esitetyt taulukot ovat Overleaf-alustalla tuotettuja Scalable Vector Graphics (SVG) -tiedostoja. Merkinnät (nuolet ja vihreät laatikot) lisättiin avaamalla SVG-grafiikka Inkscapessa — huomaa kuitenkin, että merkintöjen teksti ladottiin $$\mathrm\TeX$$ taulukon yhteyteen lisättynä lisätekstinä: Inkscapessa lisättiin vain nuolet ja vihreät taustat. Jos haluat tietää, miten tämä tehtiin, jatka lukemista.

Overleafin palvelimet käyttävät $$\mathrm\TeX \text{ Live}$$ jakelua, joka tarjoaa lisäksi $$\mathrm\TeX$$-pohjaisten ladontaohjelmien lisäksi runsaasti erittäin hyödyllisiä $$\mathrm\TeX$$-aiheisia ohjelmistotyökaluja ja apuohjelmia. Niiden joukossa on yksi nimeltä [`dvisvgm`](https://dvisvgm.de) joka, kuten sen nimi vihjaa, muuntaa $$\mathrm\TeX$$perinteisen DVI-muodon (**D**e**V**ice **I**ndependent) -tulostiedostomuodon SVG:ksi. Sen monien [komentoriviasetusten](https://dvisvgm.de/Manpage/) `dvisvgm` joukossa on asetus (`-n` tai `--no-fonts`) joka ohjaa sen muuntamaan kaiken tekstin *poluiksi* mikä tarkoittaa, että SVG-grafiikan teksti piirretään viivoilla ja käyrillä varsinaisten fonttien ja glyyffien sijaan. Tämä saattaa kasvattaa syntyvän SVG-grafiikan tiedostokokoa, mutta se varmistaa, että SVG-grafiikka on erittäin siirrettävää ja toimii lähes varmasti hyvin millä tahansa laitteella.

### Joten... miten se tehtiin?

Eräässä [aiemmassa artikkelissa](https://www.overleaf.com/blog/510-using-luatex-to-run-tools-and-utilities-installed-on-overleafs-servers) keskustelin siitä, miten voit käyttää $$\text{Lua}\mathrm\TeX$$ suorittaaksesi erilaisia Overleafin palvelimille asennettuja ohjelmistotyökaluja ja apuohjelmia — se on äärimmäisen helppo ja kätevä tekniikka. Tätä tekniikkaa käytettiin ladottujen $$\mathrm\TeX$$ taulukoiden SVG-grafiikoiden luomiseen seuraavasti. Pää $$\mathrm\TeX$$ dokumenttitiedostosta kunkin taulukon latomiskoodi (luotu käyttämällä `\halign`) kirjoitettiin `.tex` -tiedostoon. Tämä tehtiin sulkemalla taulukon koodi kahden komennon väliin, joita kutsuin `\beginscoop` ja `\endscoop`. Halutun tuloksen saavuttamiseen on todennäköisesti monia muitakin tapoja, mutta tässä ovat käyttämäni makromääritelmät:

```latex
\def\cc{\catcode`\#=12\relax}
\long\def\scoop#1\endscoop{\global\fulltoks={#1}\egroup}
\def\beginscoop{\global\advance\numfigs by1\relax\bgroup\cc\scoop}
```

Käytät niitä näin:

```latex
\beginscoop
\\halign{...}
\endscoop
```

Huomaa, että `\endscoop` token toimii vain `\scoop` makrolle: $$\mathrm\TeX$$ käytännössä hylkää `\endscoop` tokenin, joten meidän ei itse asiassa tarvitse määrittää sitä (esim. komennolla `\def\endscoop{...}`).

Se $$\mathrm\TeX$$ koodin, joka sisältyy `\\halign{...}` tallennetaan `toks` rekisteriin nimeltä `\fulltoks`. Yksi hankala kohta, johon törmäsin ( $$\text{Lua}\mathrm\TeX$$) oli tarve estää `#` merkit `\\halign{...}` esipuheessa “kaksinkertaistumasta” `##` kirjoitettaessa `.tex` -tiedostoon. Tämän välttämiseksi minun oli tilapäisesti asetettava `\catcode`kohteelle `#` merkkien catcode-arvoksi 12 ennen kuin tallensin $$\mathrm\TeX$$ koodin (tokenit) `\fulltoks` token-rekisteriin.

Seuraava vaihe on kirjoittaa sisällä olevat tokenit `\fulltoks` muotoon $$\mathrm\TeX$$ -tiedostoksi — koska käytin $$\text{Lua}\mathrm\TeX$$ tämä osoittautui *erittäin* helpoksi kiitos $$\text{Lua}\mathrm\TeX$$n ihmeellisen Lua-API:n. Lyhyesti sanottuna kirjoitin makron nimeltä `\writefile{...}` joka ottaa parametrikseen sen token-rekisterin nimen, jonka tokenit haluat kirjoittaa tiedostoon (esim. `\writefile{fulltoks}`). Sisällä `\writefile{...}` makrossa käytin Lua-API:a saadakseni tekstuaalisen esityksen `\fulltoks` token-rekisteristä:

```latex
\def\writefile#1{%
\directlua{
...
...
 local p=tex.toks["#1"]
...
...
}}
```

Tässä on kuvakaappaus, joka näyttää hieman enemmän `\writefile{...}` komento:

[![{{{alt}}}](/files/d074118d3ddc631a1db7ab7b1ccbb9fe96ed1435)](https://www.filepicker.io/api/file/ngeDmgRStGWvG044RE1A)

Lua-kieli ja tarjottu Lua-API $$\text{Lua}\mathrm\TeX$$ voivat usein yksinkertaistaa $$\mathrm\TeX$$ ohjelmointitehtäviä, ja juuri näiden hyödyllisten ja tehokkaiden ominaisuuksien vuoksi olen käyttänyt $$\text{Lua}\mathrm\TeX$$ vuodesta \~2009 lähtien — ja olen edelleen tämän $$\mathrm\TeX$$ todella ihmeellisen $$\text{Lua}\mathrm\TeX$$ moottorin suuri fani. Okei, mainos

Saatuani näin helposti $$\mathrm\TeX$$ koodin, joka on tallennettu `\fulltoks` se kirjoitetaan tiedostoon yhdessä lisäkoodin kanssa, jotta siitä saadaan oikein muodostettu $$\mathrm\LaTeX$$ -tiedosto. Seuraavat vaiheet ovat:

1. Käsittele `.tex` tiedosto, joka sisältää taulukkomme, käyttäen $$\text{pdf}\mathrm\LaTeX$$ (DVI-tilassa), jotta se lataa taulukon ja luo `.dvi` -tiedoston, jota `dvisvgm` käsittelee. Kyllä, voit käyttää $$\text{Lua}\mathrm\TeX$$ suorittaaksesi $$\text{pdf}\mathrm\LaTeX$$—käytin jälleen menetelmää, josta keskusteltiin [aiemmassa artikkelissa](/latex/fi/syvalliset-artikkelit/52-using-luatex-to-run-tools-and-utilities-installed-on-overleaf-s-servers.md).
2. Ja lopuksi suorita `dvisvgm` käsittelemään `.dvi` -tiedostoa ladotun $$\mathrm\TeX$$ taulukon SVG-grafiikan luomiseksi.
3. Varsinaiset SVG-grafiikat saat lataamalla ZIP-tiedoston Overleafistä — varmista, että valitset **Syöte- ja tulostustiedostot** vaihtoehto.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/fi/syvalliset-artikkelit/47-tex-tables-how-tex-calculates-spanned-column-widths.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
