Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 10 Min.

Der Mathe-Turbo

Schneller rechnen mit numpy, scipy und sympy.
Im ersten Teil dieser zweiteiligen Serie zum Thema Mathematik mit Python [1] wurde die Array-Klasse im Modul numpy ausführlich vorgestellt. Diese Klasse beherbergt viele Array-Operationen, die das Programmieren erheblich vereinfachen. Dieser zweite Teil der Serie lenkt den Blick auf die mathematischen Lösungsverfahren im numpy-Modul: Statistik, Polynome, lineare Algebra und Matrizen-Rechnung. Außerdem
wird das Modul scipy vorgestellt, und auch etwas symbolische Mathematik mit sympy wird noch mit dabei sein.Bei den genannten mathematischen Verfahren ist eines immer ziemlich wichtig: die Performance. Wenn man ein Gleichungssystem mit einigen Hundert Unbekannten lösen muss, dann will man nicht stundenlang auf das Ergebnis warten. Da kann ich jedoch alle Leser beruhigen: Python ist sehr schnell, insbesondere beim Lösen von Rechenaufgaben! Das liegt daran, dass die Module numpy, scipy oder auch sympy in der Programmiersprache C implementiert sind. Dabei wurden sowohl die Belange von Rechnern mit begrenzten Systemressourcen (zum Beispiel Cache-Speicher) als auch erweiterte Hardware-Ressourcen (zum Beispiel Mehrkernprozessoren) berücksichtigt.

Statistik

Die statistischen Funktionen im Modul numpy sind ein gutes Einstiegsthema, da die Berechnungen überschaubar und gut nachvollziehbar sind. Mittelwert, Medianwert und gewich­teter Durchschnitt sind leicht zu berechnen. Hier werden die FunkDabei wird ein zweidimensionales Array mithilfe des axis-Parameters in einer bestimmten Richtung verarbeitet und dann ein Ergebnisvektor zurückgegeben.Der Medianwert ist der nach dem Sortieren der Zahlen genau in der Mitte stehende Wert. Ist die Anzahl der Zahlen gerade, steht kein Wert genau in der Mitte, deshalb wird der Mittelwert zwischen den beiden mittleren Zahlen benutzt. Beim gewichteten Mittelwert muss der Funktion average ein Array mit Gewichtungen übergeben werden. Dieses Array hat die gleiche Größe wie das Daten-Array.Führen Sie das Programm aus Listing 1 aus, so erhalten Sie folgende Ergebnisse:
Listing 1: Einfache Statistik
import numpy as <span class="hljs-built_in">np</span> <br/><br/>x = <span class="hljs-built_in">np</span>.<span class="hljs-built_in">array</span>([<span class="hljs-number">1.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">9.0</span>, <span class="hljs-number">16.0</span>, <span class="hljs-number">25.0</span>]) <br/><br/># Normaler Mittelwert <br/>m1 = <span class="hljs-built_in">np</span>.<span class="hljs-built_in">mean</span>(x) <br/><span class="hljs-built_in">print</span> (<span class="hljs-string">"Mittelwert:"</span>, m1) <br/><br/># Medianwert <br/>m2 = <span class="hljs-built_in">np</span>.<span class="hljs-built_in">median</span>(x) <br/><span class="hljs-built_in">print</span> (<span class="hljs-string">"Medianwert:"</span>, m2) <br/><br/># Gewichteter Mittelwert <br/>m3 = <span class="hljs-built_in">np</span>.average(x, <br/>  weights=[<span class="hljs-number">0.5</span>, <span class="hljs-number">1.0</span>, <span class="hljs-number">2.0</span>, <span class="hljs-number">1.0</span>, <span class="hljs-number">0.5</span>]) <br/><span class="hljs-built_in">print</span> (<span class="hljs-string">"Gewichtet: "</span>, m3) 

<span class="hljs-selector-tag">Mittelwert</span>: 11<span class="hljs-selector-class">.0</span> 
<span class="hljs-selector-tag">Medianwert</span>:  9<span class="hljs-selector-class">.0</span> 
<span class="hljs-selector-tag">Gewichtet</span>:  10<span class="hljs-selector-class">.2</span> 
 
Im nächsten Schritt sollen Standardabweichung und Varianz berechnet werden. Die Funktionen dafür heißen std und var. In Listing 2 wird ein Array mit Messwerten x definiert. Die Messwerte streuen um einen mittleren Wert. Die Standardabweichung gibt nun an, wie dicht die tatsächlichen Messwerte am mittleren Wert liegen. Die Varianz ist ebenfalls ein Maß für die Streuung, wird aber etwas anders berechnet.
Listing 2: Standardabweichung und Varianz
import numpy as np &lt;br/&gt;&lt;br/&gt;x = np.array([&lt;span class="hljs-number"&gt;5.2&lt;/span&gt;, &lt;span class="hljs-number"&gt;5.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;4.8&lt;/span&gt;, &lt;span class="hljs-number"&gt;3.9&lt;/span&gt;, &lt;span class="hljs-number"&gt;4.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;5.0&lt;/span&gt;,&lt;br/&gt;  &lt;span class="hljs-number"&gt;5.2&lt;/span&gt;, &lt;span class="hljs-number"&gt;5.1&lt;/span&gt;, &lt;span class="hljs-number"&gt;4.8&lt;/span&gt;, &lt;span class="hljs-number"&gt;4.6&lt;/span&gt;]) &lt;br/&gt;&lt;br/&gt;# &lt;span class="hljs-number"&gt;1.&lt;/span&gt; Mittelwert &lt;br/&gt;m = np.mean(x); &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Mittelwert:"&lt;/span&gt; , m) &lt;br/&gt;&lt;br/&gt;# &lt;span class="hljs-number"&gt;2.&lt;/span&gt; Standardabweichung &lt;br/&gt;s = np.std(x) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Standardabweichung:"&lt;/span&gt;, s) &lt;br/&gt;&lt;br/&gt;# &lt;span class="hljs-number"&gt;3.&lt;/span&gt; Varianz &lt;br/&gt;v = np.var(x) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Varianz:"&lt;/span&gt;, v)  

Polynome

Genug Statistik, jetzt sind die Polynome an der Reihe. Ein Polynom ist eine Potenzserie mit Koeffizienten ci, die das Polynom bestimmen:

P(<span class="hljs-keyword">x</span>)=<span class="hljs-keyword">c</span><sub><span class="hljs-number">0</span></sub> + <span class="hljs-keyword">c</span><sub><span class="hljs-number">1</span></sub><span class="hljs-keyword">x</span> + <span class="hljs-keyword">c</span><sub><span class="hljs-number">2</span></sub><span class="hljs-keyword">x</span><sup><span class="hljs-number">2</span></sup> + <span class="hljs-keyword">c</span><sub><span class="hljs-number">3</span></sub><span class="hljs-keyword">x</span><sup><span class="hljs-number">3</span></sup> +...+ c<sub>n</sub>x<sup>n</sup>
 
oder etwas einfacher hingeschrieben:

<span class="hljs-function"><span class="hljs-title">P</span><span class="hljs-params">(x)</span></span> = ∑ c<sub>i</sub>x<sup>i</sup>
 
Ein Beispiel für ein Polynom zweiten Grades wäre also:

P(<span class="hljs-keyword">x</span>) = <span class="hljs-number">5</span> – <span class="hljs-number">3</span><span class="hljs-keyword">x</span> + <span class="hljs-number">2</span><span class="hljs-keyword">x</span><sup><span class="hljs-number">2</span></sup>
 
Dieses Polynom kann man in Python ganz einfach definieren, indem man ein Polynomial-Objekt anlegt und die Koeffizienten als Array übergibt. Die Reihenfolge der Koeffizienten ist dabei zu beachten: [c0, c1, c2, c3, ...].

<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np 
from numpy.polynomial <span class="hljs-keyword">import</span> Polynomial 

p = Polynomial([5.0, -3.0, 2.0]) 
print (p(4.5)) 
print (p(-1.0)) 
 
Nach der Definition des Polynomial-Objekts kann das Polynom P(x) mit beliebigen x-Werten berechnet werden. Das funktioniert natürlich auch direkt mit einem Array von x-Werten als Eingabe:

x = np.linspace(<span class="hljs-number">-5</span>, <span class="hljs-number">5</span>, <span class="hljs-number">11</span>) 
y = p(x) 
print (y) 
 
Diese Zeilen erzeugen ein Array x mit elf Werten. Als Ergebnis erhalten Sie ein Array y mit folgenden elf Polynomwerten:

[ <span class="hljs-number">70.</span>  <span class="hljs-number">49.</span>  <span class="hljs-number">32.</span>  <span class="hljs-number">19.</span>  <span class="hljs-number">10.</span>  <span class="hljs-number">5.</span>  <span class="hljs-number">4.</span>  <span class="hljs-number">7.</span>  <span class="hljs-number">14.</span>  <span class="hljs-number">25.</span>  <span class="hljs-number">40.</span>] 
 
Mit solchen Polynomial-Objekten können Sie nun auch algebraische Operationen sehr einfach durchführen. Listing 3 zeigt einige der erlaubten Möglichkeiten.
Listing 3: Polynom-Algebra
import numpy as &lt;span class="hljs-built_in"&gt;np&lt;/span&gt; &lt;br/&gt;from numpy.polynomial import Polynomial &lt;br/&gt;&lt;br/&gt;p = Polynomial([&lt;span class="hljs-number"&gt;6&lt;/span&gt;, -&lt;span class="hljs-number"&gt;5&lt;/span&gt;, &lt;span class="hljs-number"&gt;1&lt;/span&gt;]) # &lt;span class="hljs-number"&gt;6&lt;/span&gt;-5x+x**&lt;span class="hljs-number"&gt;2&lt;/span&gt; &lt;br/&gt;q = Polynomial([&lt;span class="hljs-number"&gt;2&lt;/span&gt;, -&lt;span class="hljs-number"&gt;3&lt;/span&gt;])    # &lt;span class="hljs-number"&gt;2&lt;/span&gt;-3x &lt;br/&gt;&lt;br/&gt;# Additon, Subtraktion &lt;span class="hljs-literal"&gt;und&lt;/span&gt; Multiplikation &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"Add:"&lt;/span&gt;, p + q) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"Sub:"&lt;/span&gt;, p - q) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"Mul:"&lt;/span&gt;, p * q) &lt;br/&gt;&lt;br/&gt;# Multiplikation &lt;span class="hljs-literal"&gt;und&lt;/span&gt; Division mit Skalar &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"MulSkalar:"&lt;/span&gt;, q * &lt;span class="hljs-number"&gt;3.0&lt;/span&gt;) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"DivSkalar:"&lt;/span&gt;, q / &lt;span class="hljs-number"&gt;2.0&lt;/span&gt;) &lt;br/&gt;&lt;br/&gt;# Potenzierung &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"Hoch 3:"&lt;/span&gt;, p ** &lt;span class="hljs-number"&gt;3&lt;/span&gt;) &lt;br/&gt;&lt;br/&gt;# Division &lt;br/&gt;&lt;span class="hljs-built_in"&gt;quotient&lt;/span&gt;, &lt;span class="hljs-built_in"&gt;rest&lt;/span&gt; = divmod(p, q) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"Div: "&lt;/span&gt;, &lt;span class="hljs-built_in"&gt;quotient&lt;/span&gt;) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (&lt;span class="hljs-string"&gt;"Rest:"&lt;/span&gt;, &lt;span class="hljs-built_in"&gt;rest&lt;/span&gt;)  
Zunächst werden zwei Polynome p und q definiert. Die Algebra-Funktionen werden in Python zum großen Teil mithilfe von überladenen Standardoperatoren ermöglicht. So werden Addition, Subtraktion, Multiplikation und Potenzierung mit den Operationen +, -, * und ** ausgeführt. Außerdem gibt es die Möglichkeit, ein Polynom mit einem skalaren Wert zu verarbeiten.Interessanter ist jedoch die Division zweier Polynome. Das haben wir alle irgendwann mal in der Schule gelernt! Aber Hand aufs Herz: Wer weiß noch, wie es geht?Nun ist die Sache endgültig erledigt, denn Python übernimmt das für uns. Im letzten Teil von Listing 3 wird das Polynom p durch das Polynom q dividiert. Das Ergebnis ist ein neues Polynom und zusätzlich ein übrig bleibender Restwert. Führen Sie das Programm aus Listing 3 aus, so erhalten Sie die folgenden Ausgaben:

Add: poly([ 8. <span class="hljs-string">-8</span>.  1.]) 
Sub: poly([ 4. <span class="hljs-string">-2</span>.  1.]) 
Mul: poly([ 12. <span class="hljs-string">-28</span>.  17.  <span class="hljs-string">-3</span>.]) 

MulSkalar: poly([ 6. <span class="hljs-string">-9</span>.]) 
DivSkalar: poly([ 1.  <span class="hljs-string">-1</span>.5]) 
Hoch 3: poly([ 216. <span class="hljs-string">-540</span>.  558. <span class="hljs-string">-305</span>.  93.  
              <span class="hljs-string">-15</span>.    1.]) 
Div:  poly([ 1.44444444 <span class="hljs-string">-0</span>.33333333]) 
Rest: poly([ 3.11111111]) 
 
Python gibt ein Polynom als poly(...)-Objekt aus, um es von der normalen Listenausgabe zu unterscheiden.Die Multiplikation der beiden Polynome p und q ergibt als Ergebnis ein neues poly-Objekt – das in der dritten Zeile in der Ausgabe oben:

p * q = <span class="hljs-number">12</span> – <span class="hljs-number">28</span>x + <span class="hljs-number">17</span>x<sup>2</sup> – <span class="hljs-number">3</span>x<sup>3</sup>
 
Wie wird nun der letzte Teil der Ausgabe, also das Ergebnis der Polynomdivision, interpretiert? Zunächst ist das Ergebnis von p / q wieder ein Polynom, und zwar 1.4444444 – 0.3333333x, oder etwas lesbarer: 13/9 – x/3. Der Rest der Polynomdivision ist 3.11111111 oder als Bruch: 28/9.

Die Nullstellen in Polynomen bestimmen

Und es wird noch spannender! Nun sollen die Nullstellen eines Polynoms berechnet werden. Dazu kommt das Produkt der beiden Polynome p * q aus Listing 3 zum Einsatz. Um einen Überblick über diese Funktion zu bekommen, soll sie zunächst einmal als Grafik ausgegeben werden (Listing 4).
Listing 4: Polynom für die Nullstellensuche
&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; numpy &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; np &lt;br/&gt;from numpy.polynomial &lt;span class="hljs-keyword"&gt;import&lt;/span&gt; Polynomial &lt;br/&gt;&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; matplotlib.pylab &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; plt &lt;br/&gt;&lt;br/&gt;p = Polynomial([6, -5, 1]) # 6-5x+x**2 &lt;br/&gt;q = Polynomial([2, -3])    # 2-3x &lt;br/&gt;&lt;br/&gt;x = np.linspace(0, 4, 101) &lt;br/&gt;y = (p*q)(x) &lt;br/&gt;&lt;br/&gt;plt.plot(x,y) &lt;br/&gt;plt.grid() &lt;br/&gt;plt.show()  
Hier wird eine recht interessante Syntax für die Berechnung der y-Werte benutzt: y = (p*q)(x). Es wird also zunächst die Polynommultiplikation p*q durchgeführt, dann das Ergebnis-Objekt mit dem Array der x-Werte gefüttert. Das liefert wiederum das Array der y-Werte, die dann als Grafik dargestellt werden, siehe Bild 1.
Wie Sie in der grafischen Darstellung erkennen können, hat das Polynom drei Nullstellen, was sich auch mit den Erwartungen deckt. Nun kann das Programm aus Listing 4 um zwei Zeilen erweitert werden, welche die Schnittstellen des Polynoms mit der x-Achse berechnen:

<span class="hljs-attr">nullstellen</span> = (p*q).roots() 
print (<span class="hljs-string">"Nullst.:"</span>, nullstellen) 
 
Als Ergebnis erhält man die Grafik und die drei Nullstellen: 0.6666667, 2.0 und 3.0.

Ableitungen und Integrale von Polynomen

Eigentlich sind Polynome leicht abzuleiten (differenzieren) oder zu integrieren. Dafür gibt es einige einfache Regeln, die angewendet werden müssen. Aber warum selbst rechnen, wenn es auch mit Python geht?Das Listing 4 (Nullstellen) soll nun noch um die Berechnung und die Darstellung der Ableitung und des Integrals erweitert werden. Listing 5 zeigt den kompletten Code dazu.
Listing 5: Integral und Ableitung
&lt;span class="hljs-built_in"&gt;import&lt;/span&gt; numpy as np &lt;br/&gt;from numpy.polynomial &lt;span class="hljs-built_in"&gt;import&lt;/span&gt; Polynomial &lt;br/&gt;&lt;span class="hljs-built_in"&gt;import&lt;/span&gt; matplotlib.pylab as plt &lt;br/&gt;&lt;br/&gt;&lt;span class="hljs-attr"&gt;p&lt;/span&gt; = Polynomial([&lt;span class="hljs-number"&gt;6&lt;/span&gt;, -&lt;span class="hljs-number"&gt;5&lt;/span&gt;, &lt;span class="hljs-number"&gt;1&lt;/span&gt;]) &lt;br/&gt;&lt;span class="hljs-attr"&gt;q&lt;/span&gt; = Polynomial([&lt;span class="hljs-number"&gt;2&lt;/span&gt;, -&lt;span class="hljs-number"&gt;3&lt;/span&gt;])    &lt;br/&gt;&lt;span class="hljs-attr"&gt;x&lt;/span&gt; = np.linspace(&lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-number"&gt;4&lt;/span&gt;, &lt;span class="hljs-number"&gt;101&lt;/span&gt;) &lt;br/&gt;&lt;span class="hljs-attr"&gt;y&lt;/span&gt; = (p*q)(x) &lt;br/&gt;&lt;span class="hljs-attr"&gt;p1&lt;/span&gt; = (p*q).deriv() &lt;br/&gt;&lt;span class="hljs-attr"&gt;p2&lt;/span&gt; = (p*q).integ() &lt;br/&gt;&lt;br/&gt;plt.plot(x,y) &lt;br/&gt;plt.plot(x,p1(x), &lt;span class="hljs-attr"&gt;color=’k’)&lt;/span&gt; &lt;br/&gt;plt.plot(x,p2(x), &lt;span class="hljs-attr"&gt;color=’r’)&lt;/span&gt; &lt;br/&gt;plt.grid() &lt;br/&gt;plt.show() &lt;br/&gt;&lt;br/&gt;&lt;span class="hljs-attr"&gt;nullstellen&lt;/span&gt; = (p*q).roots() &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Nullst.:"&lt;/span&gt;, nullstellen) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Ableitung:"&lt;/span&gt;, p1) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Integral: "&lt;/span&gt;, p2)  
Die Berechnung der ersten Ableitung wird durch den Aufruf der Funktion deriv ermöglicht. Direkt danach wird die Integration durchgeführt. In beiden Fällen wird als Ergebnis wieder ein Polynomial-Objekt geliefert (hier: p1 und p2). Diese Polynome werden dann in die Grafik eingezeichnet (Funktion: blau, Ableitung: schwarz und Integral: rot). Nach den Nullstellen werden die Ergebnispolynome in der bekannten Schreibweise als poly-Objekte ausgegeben:

Ableitung: poly([<span class="hljs-string">-28</span>. 34. <span class="hljs-string">-9</span>.]) 
Integral:  poly([  0. 12. <span class="hljs-string">-14</span>. 5.66666667  <span class="hljs-string">-0</span>.75 ]) 

Lineare Algebra

In diesem Abschnitt geht es noch einmal um grundlegende Matrix-Operationen, die teilweise schon in [1] beschrieben wurden. Eine der wichtigsten Operationen mit Matrizen ist die Matrixmultiplikation, die in den Naturwissenschaften immer wieder benutzt wird. Aus diesem Grund sollte die Funktion für die Multiplikation zweier Matrizen auch möglichst schnell arbeiten.Eine Skalar-Multiplikation wird mit einem numpy-Array über den normalen Multiplikationsoperator ausgeführt:

import numpy as np 
a = np.array(<span class="hljs-string">[[2.5, 1.0], [0.5, 3.0]]</span>) 
<span class="hljs-built_in">print</span> (a) 
b = a * <span class="hljs-number">3.0</span>; # Skalarmultiplikation 
<span class="hljs-built_in">print</span> (b)↓ 
In diesem Fall wird einfach jedes Array-Element in a mit 3.0 multipliziert. Das Ergebnis-Array hat die gleiche Größe wie das Ausgangs-Array.Die Multiplikation zweier Matrizen wird mit np.dot oder np.matmul ausgeführt. Das Beispiel in Listing 6 zeigt drei mögliche Implementierungen: Zunächst eine sehr einfache Eigen­implementierung mit den drei üblichen, ineinander geschachtelten Schleifen. Danach kommen die einfachen Aufrufe der Funktionen im numpy-Modul.
Listing 6: Matrizen multiplizieren
import numpy as &lt;span class="hljs-built_in"&gt;np&lt;/span&gt; &lt;br/&gt;&lt;br/&gt;a = &lt;span class="hljs-built_in"&gt;np&lt;/span&gt;.&lt;span class="hljs-built_in"&gt;array&lt;/span&gt;([[&lt;span class="hljs-number"&gt;2.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;1.0&lt;/span&gt;], [&lt;span class="hljs-number"&gt;0.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;3.0&lt;/span&gt;]]) &lt;br/&gt;b = &lt;span class="hljs-built_in"&gt;np&lt;/span&gt;.&lt;span class="hljs-built_in"&gt;array&lt;/span&gt;([[&lt;span class="hljs-number"&gt;1.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;2.0&lt;/span&gt;], [&lt;span class="hljs-number"&gt;1.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;2.5&lt;/span&gt;]]) &lt;br/&gt;&lt;br/&gt;# Eigener, sehr einfacher  Algorithmus &lt;br/&gt;c = &lt;span class="hljs-built_in"&gt;np&lt;/span&gt;.zeros([&lt;span class="hljs-number"&gt;2&lt;/span&gt;, &lt;span class="hljs-number"&gt;2&lt;/span&gt;]) &lt;br/&gt;&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; i &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; &lt;span class="hljs-built_in"&gt;range&lt;/span&gt;(&lt;span class="hljs-number"&gt;2&lt;/span&gt;): &lt;br/&gt;  &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; j &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; &lt;span class="hljs-built_in"&gt;range&lt;/span&gt;(&lt;span class="hljs-number"&gt;2&lt;/span&gt;): &lt;br/&gt;    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; k &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; &lt;span class="hljs-built_in"&gt;range&lt;/span&gt;(&lt;span class="hljs-number"&gt;2&lt;/span&gt;): &lt;br/&gt;      c[i, j] += a[i, k] * b[k, j] &lt;br/&gt;&lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (c) &lt;br/&gt;&lt;br/&gt;# Eingebauter Algorithmus &lt;br/&gt;d = &lt;span class="hljs-built_in"&gt;np&lt;/span&gt;.dot(a, b) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (d) &lt;br/&gt;&lt;br/&gt;e = &lt;span class="hljs-built_in"&gt;np&lt;/span&gt;.matmul(a, b) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;print&lt;/span&gt; (e)  
Alle drei Implementierungen liefern wie erwartet das gleiche Ergebnis-Array:

[[ <span class="hljs-number">5.25</span>  <span class="hljs-number">7.5</span> ] 
 [ <span class="hljs-number">5.25</span>  <span class="hljs-number">8.5</span> ]] 
 
Für zweidimensionale Arrays liefert die Funktion np.dot das gleiche Ergebnis wie die Funktion np.matmul. Bei eindimensionalen Vektoren wird das sogenannte innere Produkt ermittelt. Bei Arrays mit mehr als drei Dimensionen werden die Produkte über die beiden letzten Achsen summiert.
Da die Matrixmultiplikation für alle Bereiche der Naturwissenschaften und Technik enorm wichtig ist, sollen hier noch einmal einige Performance-Vergleiche durchgeführt werden. Grundsätzlich sollten Sie beim Betrachten der Ergebnisse  allerdings mehrere Dinge im Hinterkopf haben:
  • Man kann unterschiedlich leistungsfähige Algorithmen implementieren.
  • Es werden unterschiedliche Sprachen und Laufzeitumgebungen verglichen.
  • Man kann Parallelprogrammierung einsetzen.
Diese unterschiedlichen Verfahren führen erwartungsgemäß auch zu sehr unterschiedlichen Laufzeiten, siehe Bild 3.
Der Python-Code für das Beispiel befindet sich in der Datei CodeZuBild3.py im Download zu diesem Artikel und wird hier im Text nicht aufgelistet, da er Listing 6 stark ähnelt. Die erforderlichen großen Arrays wurden einfach mit Zufallszahlen initialisiert.Alle Spalten in Bild 3, die mit (1) gekennzeichnet sind, laufen in einer parallelen Umgebung mit vier Threads. Man kann erkennen, dass die normalen Rechenoperationen in Python relativ langsam sind, die entsprechenden Bibliotheksfunktionen jedoch eine sehr gute Performance zeigen. Die .NET-Sprache C# liegt etwa in der Mitte.Es stellt sich die Frage, warum die Python-Funktionen np.dot und np.matmul so schnell sind? Die Antwort ist einfach: Optimierung! Hier kommen viele Möglichkeiten zum Einsatz: Loop Unrolling, optimale Cache-Ausnutzung, rich­tige Indizierung der Arrays, Pallelisierung mit SSE und ­Threads oder spezielle Prozessorbefehle (wie zum Beispiel FusedMultiplyAndAdd). Es sollte klar sein, dass die Eigenimplementierung der Matrixmultiplikation (drei Schleifen) die einfachste und leider auch langsamste Variante ist. Dies gilt insbesondere für sehr große Arrays.

Gleichungssysteme lösen

Ein anderer wichtiger Bereich der linearen Algebra ist die Lösung von linearen Gleichungssystemen mit mehreren Unbekannten. Vielleicht erinnern Sie sich noch daran, wie Sie in der Schule Gleichungssysteme mit drei Unbekannten gelöst haben – mit viel Schweiß auf der Stirn!Das soll nun anders werden. Hierzu wird die Funktion np.linalg.solve eingesetzt. Ein Gleichungssystem mit drei Unbekannten sieht allgemein so aus:

<span class="hljs-name">m</span><sub><span class="hljs-name">11</span></sub> x<sub><span class="hljs-number">1</span></sub> + <span class="hljs-name">m</span><sub><span class="hljs-name">12</span></sub> x<sub><span class="hljs-number">2</span></sub> + <span class="hljs-name">m</span><sub><span class="hljs-name">13</span></sub> x<sub><span class="hljs-number">3</span></sub> = b<sub><span class="hljs-number">1</span></sub>
<span class="hljs-name">m</span><sub><span class="hljs-name">21</span></sub> x<sub><span class="hljs-number">1</span></sub> + <span class="hljs-name">m</span><sub><span class="hljs-name">22</span></sub> x<sub><span class="hljs-number">2</span></sub> + <span class="hljs-name">m</span><sub><span class="hljs-name">23</span></sub> x<sub><span class="hljs-number">2</span></sub> = b<sub><span class="hljs-number">2</span></sub>
<span class="hljs-name">m</span><sub><span class="hljs-name">31</span></sub> x<sub><span class="hljs-number">1</span></sub> + <span class="hljs-name">m</span><sub><span class="hljs-name">32</span></sub> x<sub><span class="hljs-number">2</span></sub> + <span class="hljs-name">m</span><sub><span class="hljs-name">33</span></sub> x<sub><span class="hljs-number">3</span></sub> = b<sub><span class="hljs-number">3</span></sub>
 
Diese drei Gleichungen können auch in einer Matrixschreibweise geschrieben werden: M x = b. Hierbei ist M die Matrix der Koeffizienten. Diese Matrix und der Vektor b müssen der Funktion np.linalg.solve zur Verfügung gestellt werden, um daraus den Lösungsvektor x zu ermitteln. Listing 7 zeigt ein Beispiel mit den drei folgenden Gleichungen:
Listing 7: Lineares Gleichungssystem lösen
import numpy as np &lt;br/&gt;&lt;br/&gt;# Arrays definieren &lt;br/&gt;M = np.array([[&lt;span class="hljs-number"&gt;3&lt;/span&gt;, &lt;span class="hljs-number"&gt;-2&lt;/span&gt;, &lt;span class="hljs-number"&gt;0&lt;/span&gt;], [&lt;span class="hljs-number"&gt;-2&lt;/span&gt;, &lt;span class="hljs-number"&gt;1&lt;/span&gt;, &lt;span class="hljs-number"&gt;-3&lt;/span&gt;], [&lt;span class="hljs-number"&gt;4&lt;/span&gt;, &lt;span class="hljs-number"&gt;6&lt;/span&gt;, &lt;span class="hljs-number"&gt;1&lt;/span&gt;]]) &lt;br/&gt;b = np.array([&lt;span class="hljs-number"&gt;8&lt;/span&gt;, &lt;span class="hljs-number"&gt;-20&lt;/span&gt;, &lt;span class="hljs-number"&gt;7&lt;/span&gt;]) &lt;br/&gt;&lt;br/&gt;# Gleichungssystem lösen &lt;br/&gt;x = np.linalg.solve(M, b) &lt;br/&gt;&lt;br/&gt;print (x)  

 <span class="hljs-number">3</span>x – <span class="hljs-number">2</span>y      =  <span class="hljs-number">8</span> 
<span class="hljs-number">-2</span>x +  y - <span class="hljs-number">3</span>z  = <span class="hljs-number">-20</span> 
 <span class="hljs-number">4</span>x + <span class="hljs-number">6</span>y +  z  =  <span class="hljs-number">7</span> 
 
Das wirklich einfache Python-Programm aus Listing 7 liefert die drei Unbekannten x, y und z als Lösungsvektor (Array):

[ <span class="hljs-number">2.</span> <span class="hljs-number">-1.</span>  <span class="hljs-number">5.</span>] 

Interpolation

Als Nächstes soll das Modul scipy zum Einsatz kommen. Unter vielen anderen Möglichkeiten findet man hier auch die Definitionen verschiedener naturwissenschaftlicher Konstanten, und zwar mit dem Wert, der Maßeinheit und dem jeweiligen Messfehler.Im folgenden Beispiel sollen die Interpolationsmöglichkeiten (mit einer Variablen) im Modul scipy genauer betrachtet werden. Eine Interpolation von mehreren diskreten Datenwerten kann auf unterschiedliche Weisen ausgeführt werden und liefert dann auch voneinander abweichende Ergebnisse. Im gezeigten Beispiel (Listing 8) werden zwei Arrays angelegt, welche die gemessenen Werte (tmess und ymess) enthalten. Danach werden diese Daten als Grafik dargestellt. Nun kann die Interpolation (Funktion interp1d) ausgeführt werden. Es müssen die Daten-Arrays und die gewünschte Interpolationsart angegeben werden.
Listing 8: Interpolation
&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; numpy &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; np &lt;br/&gt;&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; matplotlib.pylab &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; plt &lt;br/&gt;&lt;span class="hljs-keyword"&gt;from&lt;/span&gt; scipy.interpolate &lt;span class="hljs-keyword"&gt;import&lt;/span&gt; interp1d &lt;br/&gt;&lt;br/&gt;# Messwerte: &lt;br/&gt;tmess = np.array([&lt;span class="hljs-number"&gt;0.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;2.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;4.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;6.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;8.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;10.0&lt;/span&gt;]) &lt;br/&gt;ymess = np.array([&lt;span class="hljs-number"&gt;0.4&lt;/span&gt;, &lt;span class="hljs-number"&gt;25.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;142.5&lt;/span&gt;, &lt;span class="hljs-number"&gt;155.6&lt;/span&gt;, &lt;span class="hljs-number"&gt;152.3&lt;/span&gt;,&lt;br/&gt;                  &lt;span class="hljs-number"&gt;112.2&lt;/span&gt;]) &lt;br/&gt;&lt;br/&gt;# Darstellung als Punkte &lt;br/&gt;plt.plot(tmess, ymess, &lt;span class="hljs-string"&gt;'o'&lt;/span&gt;) &lt;br/&gt;plt.grid() &lt;br/&gt;&lt;br/&gt;# Interpolation &lt;br/&gt;# kind=linear, quadratic, cubic, nearest... &lt;br/&gt;f_inter = interp1d(tmess, ymess, kind=&lt;span class="hljs-string"&gt;'linear'&lt;/span&gt;) &lt;br/&gt;&lt;br/&gt;# Berechnung und Darstellung der &lt;br/&gt;# interpolierten Werte &lt;br/&gt;x = np.linspace(&lt;span class="hljs-number"&gt;0.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;10.0&lt;/span&gt;, &lt;span class="hljs-number"&gt;100&lt;/span&gt;) &lt;br/&gt;plt.plot(x, f_inter(x)) &lt;br/&gt;plt.show() &lt;br/&gt;&lt;br/&gt;# Berechnung bestimmter interpolierter Werte &lt;br/&gt;print(&lt;span class="hljs-string"&gt;"X = 3.0, Y ="&lt;/span&gt;, f_inter(&lt;span class="hljs-number"&gt;3.0&lt;/span&gt;)) &lt;br/&gt;print(&lt;span class="hljs-string"&gt;"X = 5.0, Y ="&lt;/span&gt;, f_inter(&lt;span class="hljs-number"&gt;5.0&lt;/span&gt;))  
benutzt werden. Das bedeutet, dass der Teil zwischen zwei Messpunkten jeweils durch eine Gerade interpoliert wird. Als Ergebnis erhält man eine Funktion, die eingesetzt werden kann, um beliebige Werte zwischen den diskreten Messwerten zu berechnen. Im Beispielcode wird die Ergebnisfunk­tion ebenfalls gezeichnet, zu sehen ist sie in Bild 4. Schließlich werden zwei interpolierte Werte an den Stellen 3.0 und 5.0 berechnet und ausgegeben.
Die Funktion interp1d aus dem Modul scipy ermittelt ein Rückgabeobjekt, das die interpolierte Funktion abbildet. Dieses Objekt kann also benutzt werden, um beliebige Interpolationswerte auszurechnen. Man muss jedoch beachten, dass die berechneten Werte im Definitionsbereich der interpolierten Daten liegen. Im gezeigten Beispiel müssen die x-Werte also zwischen 0.0 und 10.0 liegen.Die Bibliothek stellt unterschiedliche Interpolationsarten zur Verfügung. Die in Listing 8 angewendete Art linear verbindet die einzelnen diskreten Datenpunkte durch einfache Geradensegmente. Die Interpolationsart quadratic erzeugt quadratische, cubic erstellt kubische Spline-Funktionen, welche die Daten optimal abbilden.

Symbolische Mathematik mit sympy

Das Python-Modul sympy enthält viele Klassen, die symbolische Mathematik ermöglichen. Das bedeutet vereinfacht ausgedrückt, dass man direkt mit mathematischen Formeln rechnen kann. Sie können also einen mathematischen Ausdruck umstellen oder vereinfachen. Als Ergebnis erhalten Sie einen neuen mathematischen Ausdruck.Das hört sich ja sehr gut an! Wie oft haben wir in der Schule vor mathematischen Ausdrücken gesessen und mussten diese vereinfachen oder umstellen? Auch das wird nun dank Python und der Bibliothek sympy wesentlich einfacher. Hier ein einführendes Beispiel:

import sympy 
# Ausdruck definieren 
expr = <span class="hljs-number">2</span>*(<span class="hljs-keyword">x</span>**<span class="hljs-number">2</span> - <span class="hljs-keyword">x</span>) - <span class="hljs-keyword">x</span>*(<span class="hljs-keyword">x</span> + <span class="hljs-number">2</span>) 
# Ausdruck vereinfachen 
result = sympy.simplify(expr) 
print (<span class="hljs-string">"Ausdruck:  "</span>, expr) 
print (<span class="hljs-string">"Vereinfacht:"</span>, result) 
 
Zunächst wird das Modul sympy importiert. Dann definiert man einen mathematischen Ausdruck, der anschließend mit der Funktion simplify vereinfacht wird. Das Ergebnis lautet im vorliegenden Fall so:
x*(<span class="hljs-name">x</span> - <span class="hljs-number">4</span>) 
Das sieht schon einmal sehr gut aus, aber leider ist es nicht in allen Fällen so einfach. Der folgende Code soll den Ausdruck sqrt(x**2) vereinfachen. Die Quadratwurzel einer quadrierten Zahl sollte die Zahl selbst ergeben. Als Ergebnis erwartet man also x. Der erste Teil des unten gezeigten Programmcodes verändert den Ausdruck aber gar nicht.Erst im zweiten Teil funktioniert alles wie gewünscht. Dort wurde das Symbol y so definiert, dass es immer einen positiven Wert enthalten soll. Lediglich unter dieser Bedingung ist die Wurzel-Funktion nämlich erlaubt und das Ergebnis ist dann x.

<span class="hljs-keyword">import</span> sympy 

x = sympy.Symbol(<span class="hljs-string">"x"</span>) 
<span class="hljs-built_in">print</span> (sympy.<span class="hljs-built_in">sqrt</span>(x**<span class="hljs-number">2</span>)) 

y = sympy.Symbol(<span class="hljs-string">"y"</span>, positive=<span class="hljs-literal">True</span>) 
<span class="hljs-built_in">print</span> (sympy.<span class="hljs-built_in">sqrt</span>(y**<span class="hljs-number">2</span>)) 
 
Zum Abschluss möchte ich ein kleines (ganz einfaches) Mathematikprogramm erstellen, das mit Ausdrücken arbeiten kann. Es soll einen Ausdruck vereinfachen, ausmultiplizieren, faktorisieren, differenzieren oder integrieren können, siehe Listing 9. Die Benutzerschnittstelle wurde dabei bewusst einfach gehalten, da es hier nur um die Benutzung der Funktionalitäten im Modul sympy geht. Am Anfang des Programms wird das Symbol x explizit definiert. Dadurch vermeidet man im folgenden Code die Warnung, dass x undefiniert sei. Danach wird der mathematische Ausdruck als normale String-Variable eingelesen und die Rechenoperation abgefragt.
Listing 9: Einfaches Mathematik-Programm
&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; sympy &lt;br/&gt;&lt;br/&gt;x = sympy.&lt;span class="hljs-type"&gt;Symbol&lt;/span&gt;(&lt;span class="hljs-string"&gt;"x"&lt;/span&gt;) &lt;br/&gt;&lt;span class="hljs-built_in"&gt;expr&lt;/span&gt; = input(&lt;span class="hljs-string"&gt;"Ausdruck f(x): "&lt;/span&gt;) &lt;br/&gt;&lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Was soll gemacht werden:"&lt;/span&gt;) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"   (v)ereinfachen"&lt;/span&gt;) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"   (a)usmultiplizieren"&lt;/span&gt;) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"   (f)aktorisieren"&lt;/span&gt;) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"   nach x (d)ifferenzieren"&lt;/span&gt;) &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"   über x (i)ntegrieren"&lt;/span&gt;) &lt;br/&gt;todo = input(&lt;span class="hljs-string"&gt;"v, a, f, d oder i: "&lt;/span&gt;) &lt;br/&gt;&lt;br/&gt;&lt;span class="hljs-keyword"&gt;if&lt;/span&gt;(todo == 'v'): &lt;br/&gt;    &lt;span class="hljs-literal"&gt;result&lt;/span&gt; = sympy.simplify(&lt;span class="hljs-built_in"&gt;expr&lt;/span&gt;) &lt;br/&gt;&lt;span class="hljs-keyword"&gt;elif&lt;/span&gt;(todo == 'a'): &lt;br/&gt;    &lt;span class="hljs-literal"&gt;result&lt;/span&gt; = sympy.expand(&lt;span class="hljs-built_in"&gt;expr&lt;/span&gt;) &lt;br/&gt;&lt;span class="hljs-keyword"&gt;elif&lt;/span&gt;(todo == 'f'): &lt;br/&gt;    &lt;span class="hljs-literal"&gt;result&lt;/span&gt; = sympy.factor(&lt;span class="hljs-built_in"&gt;expr&lt;/span&gt;)    &lt;br/&gt;&lt;span class="hljs-keyword"&gt;elif&lt;/span&gt;(todo == 'd'): &lt;br/&gt;    &lt;span class="hljs-literal"&gt;result&lt;/span&gt; = sympy.diff(&lt;span class="hljs-built_in"&gt;expr&lt;/span&gt;, x) &lt;br/&gt;&lt;span class="hljs-keyword"&gt;elif&lt;/span&gt;(todo == 'i'): &lt;br/&gt;    &lt;span class="hljs-literal"&gt;result&lt;/span&gt; = sympy.integrate(&lt;span class="hljs-built_in"&gt;expr&lt;/span&gt;, x) &lt;br/&gt;    &lt;br/&gt;print (&lt;span class="hljs-string"&gt;"Ergebnis:"&lt;/span&gt;, &lt;span class="hljs-literal"&gt;result&lt;/span&gt;)  
Mithilfe mehrerer if-Befehle wird nun die gewünschte Operation auf den Ausdruck angewendet und als Ergebnis ausgegeben. Ein Beispiellauf des Programms könnte wie folgt aussehen:

<span class="hljs-selector-tag">Ausdruck</span> <span class="hljs-selector-tag">f</span>(x): <span class="hljs-selector-tag">2</span>*<span class="hljs-selector-tag">exp</span>(-<span class="hljs-number">0.5</span>*x)/<span class="hljs-selector-tag">x</span> 

<span class="hljs-selector-tag">Was</span> <span class="hljs-selector-tag">soll</span> <span class="hljs-selector-tag">gemacht</span> <span class="hljs-selector-tag">werden</span>: 
  (v)<span class="hljs-selector-tag">ereinfachen</span> 
  (a)<span class="hljs-selector-tag">usmultiplizieren</span> 
  (f)<span class="hljs-selector-tag">aktorisieren</span> 
  <span class="hljs-selector-tag">nach</span> <span class="hljs-selector-tag">x</span> (d)<span class="hljs-selector-tag">ifferenzieren</span> 
  ü<span class="hljs-selector-tag">ber</span> <span class="hljs-selector-tag">x</span> (i)<span class="hljs-selector-tag">ntegrieren</span> 

<span class="hljs-selector-tag">v</span>, <span class="hljs-selector-tag">a</span>, <span class="hljs-selector-tag">f</span>, <span class="hljs-selector-tag">d</span> <span class="hljs-selector-tag">oder</span> <span class="hljs-selector-tag">i</span>: <span class="hljs-selector-tag">d</span> 
<span class="hljs-selector-tag">Ergebnis</span>: <span class="hljs-selector-tag">-1</span><span class="hljs-selector-class">.0</span>*<span class="hljs-selector-tag">exp</span>(-<span class="hljs-number">0.5</span>*x)/<span class="hljs-selector-tag">x</span> <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">2</span>*<span class="hljs-selector-tag">exp</span>(-<span class="hljs-number">0.5</span>*x)/<span class="hljs-selector-tag">x</span>**<span class="hljs-selector-tag">2</span> 

Zusammenfassung

Das ist erwartungsgemäß noch längst nicht alles, was Python in Sachen Mathematik draufhat. Die Möglichkeiten von numpy, scipy und sympy konnten in diesem zweiteiligen Artikel gerade einmal angerissen werden. Viele Klassen, die Verfahren für die höhere Mathematik bereitstellen, wurden hier nicht angesprochen, da sie nur in ganz speziellen Fällen benötigt werden. Einige Erkenntnisse sollen aber noch einmal herausgestellt werden:
  • Python ist bei mathematischen Berechnungen nicht langsam, sondern besonders flott.
  • Python enthält sehr umfangreiche Mathe-Bibliotheken.
  • Die Benutzung der Klassen ist sehr einfach.
  • Viele Programmierfehler können durch die Benutzung der Bibliotheken vermieden werden.
  • Letztendlich kann man eine Menge Zeit sparen.
Auf den Punkt gebracht: Mit Python macht Mathematik wieder so richtig Spaß!
Projektdateien herunterladen

Fussnoten

  1. Bernd Marquard, Rechnen mit Python, Teil 1, Arrays mit Schleife, dotnetpro 12/2017, Seite 64 ff., http://www.dotnetpro.de/A1712Rechnen

Neueste Beiträge

DWX hakt nach: Wie stellt man Daten besonders lesbar dar?
Dass das Design von Websites maßgeblich für die Lesbarkeit der Inhalte verantwortlich ist, ist klar. Das gleiche gilt aber auch für die Aufbereitung von Daten für Berichte. Worauf besonders zu achten ist, erklären Dr. Ina Humpert und Dr. Julia Norget.
3 Minuten
27. Jun 2025
DWX hakt nach: Wie gestaltet man intuitive User Experiences?
DWX hakt nach: Wie gestaltet man intuitive User Experiences? Intuitive Bedienbarkeit klingt gut – doch wie gelingt sie in der Praxis? UX-Expertin Vicky Pirker verrät auf der Developer Week, worauf es wirklich ankommt. Hier gibt sie vorab einen Einblick in ihre Session.
4 Minuten
27. Jun 2025
„Sieh die KI als Juniorentwickler“
CTO Christian Weyer fühlt sich jung wie schon lange nicht mehr. Woran das liegt und warum er keine Angst um seinen Job hat, erzählt er im dotnetpro-Interview.
15 Minuten
27. Jun 2025
Miscellaneous

Das könnte Dich auch interessieren

UIs für Linux - Bedienoberflächen entwickeln mithilfe von C#, .NET und Avalonia
Es gibt viele UI-Frameworks für .NET, doch nur sehr wenige davon unterstützen Linux. Avalonia schafft als etabliertes Open-Source-Projekt Abhilfe.
16 Minuten
16. Jun 2025
Mythos Motivation - Teamentwicklung
Entwickler bringen Arbeitsfreude und Engagement meist schon von Haus aus mit. Diesen inneren Antrieb zu erhalten sollte für Führungskräfte im Fokus stehen.
13 Minuten
19. Jan 2017
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige