Kirjautuminen

Haku

Tehtävät

Koodit: PHP: Laskulausekkeen muotoilu

Kirjoittaja: Antti Laaksonen

Kirjoitettu: 27.06.2004 – 27.06.2004

Tagit: grafiikka, koodi näytille, vinkki

Tämä skripti näyttää laskulausekkeen HTML-muodossa: jakolaskuissa luvut ovat allekkain ja välissä on viiva, potenssit näkyvät ylemmällä tasolla pienemmällä fontilla, neliöjuurimerkki näkyy oikeanlaisena jne. Myös kertomerkki muuttuu pisteeksi ja turhat sulut lähtevät pois. Skripti näyttää toiset kaavat paremmin, toiset taas vähän huonommin.

Skriptiin liittyvät kuvat ovat osoitteessa http://koti.mbnet.fi/pllk/muut/kaava/.

Esimerkkejä:

Skripti ei valitettavasti toimi täydellisesti Operalla, koska selain jättää neliöjuurimerkin ja sulut näyttämättä. Vika liittyy kuvan koon määrittämiseen prosenttiluvun avulla. Jos joku tietää keinon korjaamiseen, teen mielelläni tarvittavat muutokset skriptiin.

<html><body>
<?php
/*
Laskulausekkeen muotoilija, tekijä Antti Laaksonen

Tämä skripti muuttaa laskulausekkeen HTML-muotoon.

Skriptin tunnistamat merkinnät:

  +  yhteenlasku
  -  vähennyslasku
  *  kertolasku (muuttuu pisteeksi)
  /  jakolasku (lausekkeet allekkain ja viiva väliin)
  :  jakolasku (yhdellä rivillä)
  ^  potenssilasku (oikealla oleva lauseke ylemmäs ja pieneksi)
  \  neliöjuuri (lausekkeen ympärille juurimerkki)
  () suluilla voi muuttaa laskujärjestystä

Muut merkit näytetään tavallisesti.

*/

function muotoilekaava($kaava) {
   //poistetaan välilyönnit
   $kaava = str_replace(" ", "", $kaava);
   //tarkastetaan, että sulkuja on yhtä paljon
   if (substr_count($kaava, "(") <> substr_count($kaava, ")")) {
      die("Virheellinen sulkujen määrä!");
   }
   //lukuja erottavat merkit
   $erikois = array("=", "+", "-", "*", ":", "/", "^", "\\");
   //taulukon alkuattribuutit
   $talku = "cellpadding=\"0\" cellspacing=\"0\"";
   //kaavan pituus
   $pituus = strlen($kaava);
   //käydään kaavan jokainen merkki läpi
   for ($i = 0; $i < $pituus; $i++) {
      $merkki = $kaava[$i];
      //jos merkki aloittaa sulut, selvitetään sulkujen välissä oleva osuus
      //ja kutsutaan funktiota uudestaan alikaava parametrina
      if ($merkki == "(") {
         $taso = 1;
         for ($j = $i + 1; $j < $pituus; $j++) {
            if ($kaava[$j] == "(") {
               $taso++;
            } elseif ($kaava[$j] == ")") {
               $taso--;
            }
            if ($taso == 0) {
               $lista[] = "(";
               $lista[] = muotoilekaava(substr($kaava, $i + 1, $j - $i - 1));
               $lista[] = ")";
               $i = $j;
               break;
            }
         }
      //jos merkki on erotusmerkki, lisätään edellinen luku ja merkki listaan
      } elseif (in_array($merkki, $erikois)) {
         if ($tieto <> "") {
             $lista[] = $tieto;
             $tieto = "";
         }
         $lista[] = $merkki;
      //jos merkki on tavallinen merkki, laitetaan se talteen
      } else {
         if ($i == $pituus - 1) {
            $lista[] = $tieto . $merkki;
         } else {
            $tieto .= $merkki;
         }
      }
   }
   //käydään lausekkeen merkit läpi takaperin
   for ($i = count($lista) - 1; $i >= 0; $i--) {
      $osa = $lista[$i];
      //jos on jakolasku, laitetaan lausekkeet allekkain
      if ($osa == "/") {
         if ($lista[$i - 1] == ")") {
            $vasen = $lista[$i - 2];
            $lista[$i - 1] = $lista[$i - 2] = $lista[$i - 3] = "";
         } else {
            $vasen = $lista[$i - 1];
            $lista[$i - 1] = "";
         }
         if ($lista[$i + 1] == "(") {
            $oikea = $lista[$i + 2];
            $lista[$i + 1] = $lista[$i + 2] = $lista[$i + 3] = "";
         } else {
            $oikea = $lista[$i + 1];
            $lista[$i + 1] = "";
         }
         $jako = "<table $talku>";
         $jako .= "<tr><td><center>$vasen</center></td></tr>";
         $jako .= "<tr><td><img src=\"k_p.png\" width=\"100%\" height=\"1\"></td></tr>";
         $jako .= "<tr><td><center>$oikea</center></td></tr>";
         $jako .= "</table>";
         $lista[$i] = $jako;
      //jos on potenssiin korotus, laitetaan oikeanpuoleinen osuus ylemmäs pienempänä
      } elseif ($osa == "^") {
         if ($lista[$i + 1] == "(") {
            $oikea = $lista[$i + 2];
            $lista[$i + 1] = $lista[$i + 2] = $lista[$i + 3] = "";
         } else {
            $oikea = $lista[$i + 1];
            $lista[$i + 1] = "";
         }
         $oikea = str_replace("<td>", "<td><small>", $oikea);
         $oikea = str_replace("</td>", "</small></td>", $oikea);
         $jako = "<table $talku>";
         $jako .= "<tr valign=\"top\"><td><small>$oikea</small></td></tr>";
         $jako .= "<tr><td> </td></tr>";
         $jako .= "</table>";
         $lista[$i] = $jako;
      //jos neliöjuuri, laitetaan lauseke juuren sisään
      } elseif ($osa == "\\") {
         if ($lista[$i + 1] == "(") {
            $oikea = $lista[$i + 2];
            $lista[$i + 1] = $lista[$i + 2] = $lista[$i + 3] = "";
         } else {
            $oikea = $lista[$i + 1];
            $lista[$i + 1] = "";
         }
         $jako = "<table $talku>";
         $jako .= "<tr><td></td><td></td><td><img src=\"k_p.png\" width=\"100%\" height=\"1\"></td></tr>";
         $jako .= "<tr><td height=\"100%\"><img src=\"k_j.png\" height=\"100%\" width=\"9\"></td>";
         $jako .= "<td></td><td>$oikea</td></tr>";
         $jako .= "</table>";
         $lista[$i] = $jako;
      //erotusmerkkien molemmille puolille laitetaan väli, lisäksi kertomerkki muutetaan
      } elseif (in_array($osa, $erikois)) {
         $lista[$i] = " " . str_replace("*", "·", $osa) . " ";
      }
   }
   //käydään vielä kerran kaikki merkit läpi
   for ($i = 0; $i < count($lista); $i++) {
      //jos sulkuja on jäljellä, muutetaan ne sopivan kokoisiksi
      if ($lista[$i] == "(") {
         $vali = $lista[$i + 1];
         $lista[$i + 1] = $lista[$i + 2] = "";
         $jako = "<table $talku>";
         $jako .= "<tr><td height=\"100%\"><img src=\"k_sv.png\" height=\"100%\" width=\"3\"></td>";
         $jako .= "<td>$vali</td>";
         $jako .= "<td height=\"100%\"><img src=\"k_so.png\" height=\"100%\" width=\"3\"></td></tr>";
         $jako .= "</table>";
         $lista[$i] = $jako;
      }
   }
   //lopuksi kootaan yhteen äsken luodut osat, niistä tulee funktion palautusarvo
   $uusi = "<table $talku><tr>";
   for ($i = 0; $i < count($lista); $i++) {
      $uusi .= "<td>{$lista[$i]}</td>";
   }
   $uusi .= "</tr></table>";
   return $uusi;
}

//potenssisääntöjä
if ($demo == 1) {
   echo muotoilekaava("a^2 * a^5 = a^(2+5) = a^7");
//toisen asteen yhtälö
} elseif ($demo == 2) {
   echo muotoilekaava("x = (-b +\\(b^2-4*a*c))/(2*a)");
//loton päävoiton todennäköisyys
} elseif ($demo == 3) {
   echo muotoilekaava("7/39*6/38*5/37*4/36*3/35*2/34*1/33 = 1/15380937");
//yhtälön ratkaisu
} elseif ($demo == 4) {
   echo muotoilekaava("(2x-1)/7-(14-3x)/14=3x/7-1");
   echo "<br>";
   echo muotoilekaava("(4x-2)-(14-3x)=6x-14");
   echo "<br>";
   echo muotoilekaava("7x-16=6x-14");
   echo "<br>";
   echo muotoilekaava("x=2");
}

?>
</body></html>

Kommentit

peki [28.06.2004 11:28:07]

#

Oikein hyödyllinen.
Jos mahdollista, voisiko tämän saada myös oppaisiin tai keskustelualueelle?
Alaindeksi olisi hyvä olla.

Edit: Tämähän on 1000. Putkaan lähetetty koodivinkki... :D

Antti Laaksonen [28.06.2004 12:45:33]

#

Alaindeksin ja paljon muutakin voi tehdä itse HTML-komennoilla. Tageihin lisääminen on ihan hyvä idea, pitää kuitenkin vähän vielä ensin parannella tätä.

sooda [28.06.2004 13:17:35]

#

lainaus:

Tämähän on 1000. Putkaan lähetetty koodivinkki... :D

Tosiaan. :D
Oikein kiva hyödykäs koodi. Miinusta tulee kyllä tosta ettei toimi operassa :(

Turambar [28.06.2004 13:54:59]

#

Yhtälön ratkaisuun vielä ekvivalenssi- ja implikaatio-nuolet. Yleensä <=> ja => muotoutuvat rumasti.

Blaze [29.06.2004 01:58:23]

#

Hii! Kiva. Seuraavaksi MathML:ää generoiva versio? :)

moptim [18.04.2007 18:13:39]

#

Aika makia.

Malfunc [07.11.2007 19:30:52]

#

Aika hieno, mutta HTML:ssä on kyllä myös <sub> ja <sup> koodit...

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta