MathML/Algebra mit MathML und JavaScript

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
Die Algebra (von arabisch الجبر, DMG al-ǧabr „das Zusammenfügen gebrochener Teile“) ist eines der grundlegenden Teilgebiete der Mathematik; es befasst sich mit den Eigenschaften von Rechenoperationen. Im Volksmund wird Algebra häufig als das Rechnen mit Unbekannten in Gleichungen bezeichnet.

In diesem Tutorial lernen Sie, wie Sie mit MathML Gleichungen auf Webseiten darstellen und mit JavaScript deren DOM verändern.

Zinseszins

Der Zinseszins sorgt dafür, dass sich gespartes Geld munter vermehrt, aber auch vermeintlich machbare Kreditsummen über die Jahre nicht weniger werden.[1]

Zinseszinsformel ansehen …
<msub>
	<mn>K</mn>
	<mn>n</mn>
</msub>

<mo>=</mo>

<msub>
	<mn>K</mn>
	<mn>0</mn>
</msub>

<mo>*</mo>
<msup>
<mrow>
<mo>(</mo>

<mn>1</mn>
<mo>+</mo>
<mfrac>
	<mi href="https://de.wikipedia.org/wiki/Zinssatz" title="https://de.wikipedia.org/wiki/Zinssatz">p</mi>
	<mn>100</mn>
</mfrac>
<mo>)</mo>
</mrow>
<mi>n</mi>
</msup>

Links in MathML

Ist Ihnen aufgefallen, dass das <mi>-Element ein href-Attribut hat? Es ist angedacht, dies in der künfitgen Spezifikation MathML 4.0 festzulegen, im Firefox und Safari funktioniert es bereits.[2] Der Link erscheint blau - auch ein title-Attribut wird angezeigt.

In Chrome und den anderen Blink-Browsern bleibt das Element funktionslos.

So teuer ist Ihre Immobilie wirklich!

Auch in der Zeit der Niedrigzinsen, die mittlerweile fast schon vorbei scheint, ist es interessant, wie sich eine feste Summe dank Zins und Zinseszins über die Jahre zu einer erklecklichen Gesamtsumme aufbaut.

Gesucht wird die Gesamtsumme Kn - also können wir die obige Formel unverändert verwenden!

Unser Beispiel wird um ein Eingabeformular erweitert, das drei der vier Größen (oder Variablen) abfragt und dann das Ergebnis berechnet:

Eingabeformular, Verarbeitung, Ausgabe ansehen …
	const
		calculator = {},
		output = document.querySelector('output');

	function empty (node) {
		while (node.firstChild) {
			node.removeChild(node.firstChild);
		}
	}

	// DOM-Teile merken
	['principal', 'rate', 'time', 'total'].forEach(key => {
		calculator[key] = {};

		// <input>
		calculator[key].input = document.querySelector(`[name='${key}']`);
		calculator[key].parsedValue = '?';

		// Formelteil
		calculator[key].mathNode = document.querySelector(`#${key}`);
		calculator[key].mathContent = calculator[key].mathNode.firstChild;

		// finde DOMElement für Formelteil
		calculator[key].mathNode.childNodes.forEach(node => {
			if (node.tagName) {
				calculator[key].mathContent = node;
			}
		});
	});

Die Verarbeitung der eingegebenen Zahlen erfolgt nun in zwei Schritten:

  1. Die eingegebenen Werte werden benutzt, um Kn zu ermitteln und auszugeben
    1. Eingegebene Werte sind immer Strings - sie müssen mit parseFloat erst in (Dezimal)-Zahlen umgewandelt werden.
    2. Damit gerade hohe Werte wie der Kaufpreis „lesbarer“ werden, werden mit Number.toLocaleString Tausender-Separatoren eingefügt.[3]
    3. Mithilfe der Math.pow()- Funktion wird nun Kn ermittelt.
  2. Die MathML-Formel wird nun mit den eingegebenen Werten aktualisiert.
    1. Es wird mit createElement ein neues Element erzeugt und die mit event.target.value ermittelte Eingabe als Textknoten eingefügt.
    2. Kn und Ko bestehen ja aus msub-Elementen. Diese und die mi von p und n werden in je ein mrow mit einer id geschachtelt.
      Die id entspricht dem name-Attribut des jeweiligen Eingabefelds.
      Sobald eine Eingabe erfolgt, wird das msub-Element gelöscht und ein mn-Element mit dem ermittelten Wert eingefügt.
      Dies wird umstandslos mit der neuen replaceChildren-Methode erledigt.

Wie lange bis zur ersten Million?

Wenn man Geld und Zinsen einfach auf dem Konto lässt, wäre es interessant zu wissen, wann man (hoffentlich die erste von vielen weiteren) Million(en) erreicht hat.

Gesucht wird nun t, sodass wir die Gleichung umformen müssen:[4]


Umformung einer Formel ansehen …
<math class="equation" id="schritt1">
<mrow>
	<mrow>
		<msub>
			<mn>K</mn>
			<mn>n</mn>
		</msub>
  </mrow>  
		...
</mrow>    
</math>

<math class="op">
	<mrow>
		...
	</mrow>
</math>

<math class="equation" id="schritt2">
		...
</math>
Die Äquivalenzumformung besteht jeweils aus der Formel, sowie rechts dem durch einen Strich getrennten Operator. Beide werden jeweils in einer eigenen Formel notiert.
math {
  font-size: 2.5em;
	display: block;
	margin-bottom: 2em;
}

.equation > mrow >mrow:first-of-type {
    width: 250px;
    display: inline-block;
    text-align: right;
    background: yellow;
}

@media (min-width: 30em) { 
	body {
	  display: grid;
		grid-template-columns: 1fr 16em;
		max-width: 50em;
	}
}

h1, h2, p {
  grid-column: 1 / -1;
}

Per CSS werden beide Formelteile in einem Grid angeordnet. Dies funktioniert in allen Browsern problemlos.

Optimalerweise sollten die Terme links des Gleichheitszeichens die gleiche Breite haben:

.equation > mrow >mrow:first-of-type {
    width: 250px;
    display: inline-block;
    text-align: right;
    background: yellow;
}

Chrome stellt Terme nicht immer inline dar. Eine Schachtelung mit mrow schafft hier Abhilfe. Das zweite mrow-Element (bzw. das erste Kind des direkt folgenden mrow-Elements) wird nun als inline-block auf eine feste Breite von 250px gebracht.

Screenshot der mrow-Verschachtelung

Die Breitenangabe wird im Firefox 111 ignoriert; im Chrome funktioniert es, allerdings werden die Logarithmen nicht mehr inline dargestellt. Im Live-Beispiel wurden diese deshalb in einem weiteren mrow-Element geschachtelt.

<math class="equation" id="schritt3">
  <mrow>
    <mrow><!-- per CSS mit 250px Breite -->
      <mrow display="inline">
        <mo>ln</mo>
          <mfrac>
            <msub>
              <mn>K</mn>
              <mn>n</mn>
            </msub>
            <msub>
              <mn>K</mn>
              <mn>0</mn>
          </msub>
        </mfrac>
     </mrow>
  </mrow>

Was allerdings in beiden Browsern (noch) nicht funktioniert, ist die rechte Ausrichtung am Gleichheitszeichen.[5][6]

Hoffentlich gibt es hier bald Fortschritte in den Browsern!

Als ToDo könnte man die Auflösung der Gleichung automagisch durch JavaScript lösen lassen.[7]

Kapitel 2

ToDo (weitere ToDos)

Dieser Artikel sollte weiter ausgebaut werden.

Bitte schicken Sie Ideen, gute Beispiele und best-practice-Tipps an projekt@selfhtml.org.

Noch besser wäre es, wenn Sie in unserem Wiki mitmachen würden.

--Matthias Scharwies (Diskussion) 23:03, 23. Mär. 2023 (CET)

Weblinks

  1. Wikipedia: Zinseszins
  2. MDN: href in MathML
  3. Format a number with comma as a thousands separator in JS (Codingexercises)
  4. Laufzeit berechnen (mathebibel.de)
  5. SO: All terms left of = should have same length
  6. SO: Aligning mathml equations at equal sign
  7. Lösen linearer Gleichungssysteme (JavaScript) (Walter Bislin's Blog-De)


evtl: