https://delors.github.io/prog-einfuehrung/folien.de.md.html
https://delors.github.io/prog-einfuehrung/folien.de.md.html.pdf
Bei der Erstellung der Unterlagen wurden KI Assistenten (insbesondere Claude aber ggf. auch ChatGPT, Ollama mit Gemma/LLama/Qwen oder OpenCode mit Kimi/Qwen/Deepseek...) unterstützend eingesetzt. Dies erfolgte insbesondere zur Unterstützung bei der Generierung von Grafiken (d. h. SVG Dateien), oder um sich Übersichtstabellen generieren zu lassen. Weiterhin wurde KI zur allgemeinen Qualitätssicherung eingesetzt. Inhalte, die ggf. von der KI vorgeschlagen wurden, wurden im Falle der Übernahme explizit validiert und angepasst.
Einfache Programme (in Java) schreiben zu können
Grundlegende Werkzeuge für die Softwareentwicklung kennen lernen
Die Fähigkeit zum Computational Thinking (d. h. zum algorithmischen Denken) zu erwerben
Die Fähigkeit zu erwerben komplexe Probleme mittels des Prinzips divide et impera (teile und herrsche) zu lösen
Ein paar grundlegende Begriffe der Softwareentwicklung kennen lernen
AI accelerates software development to breakneck speeds, but measuring that is tricky
[...]
AI-assisted development is now the norm - 78% of survey respondents currently use AI in software development or plan to in the next two years, up from 64% in 2023.
[...]
Bringing in AI may be accelerating software development toward blinding speeds. Stunningly, most executives (69%) indicate they are shipping software twice as fast as last year.
[...]
KI: Kannibalisieren sich die Programmierer?
Viele Branchen und Berufe wurden in den letzten Jahrzehnten durch IT umgekrempelt. Laut McKinsey und IDC trifft es wegen generativer KI jetzt die IT-Branche.
Laut McKinsey sollen in den kommenden drei Jahren bis zu 250 Milliarden US-Dollar in generative KI (GenAI) [...] investiert werden. Das betrifft vor allem die Codeerstellung, den IT-Helpdesk und die Testautomatisierung. [...]
Damit [GenAI] ließe sich die Produktivität der Softwareentwickler um bis zu 50 Prozent steigern. Das betrifft vor allem die Dokumentation, die Anpassung an neue Anforderungen und Refactoring. Das wird dazu führen, dass mehr Eigenentwicklung betrieben wird und weniger Standardsoftware zum Einsatz kommt. Dieser Trend werde dadurch verstärkt, dass Citizen-Developer demnächst nicht mehr Low-Code/No-Code nutzen, sondern nur noch in natürlicher Sprache und GenAI programmieren. [...]
Devs gaining little (if anything) from AI coding assistants
Code analysis firm sees no major benefits from AI dev tool when measuring key programming metrics, though others report incremental gains from coding copilots with emphasis on code review.
Many developers say AI coding assistants make them more productive, but a recent study set forth to measure their output and found no significant gains. Use of GitHub Copilot also introduced 41% more bugs, according to the study from Uplevel, a company providing insights from coding and collaboration data.
METR previously published a paper which found the use of AI tools caused a 20% slowdown in completing tasks among experienced open-source developers, using data from February to June 2025. [...]
Unfortunately, given participant feedback and surveys, we believe that the data from our new experiment gives us an unreliable signal of the current productivity effect of AI tools. The primary reason is that we have observed a significant increase in developers choosing not to participate in the study because they do not wish to work without AI, which likely biases downwards our estimate of AI-assisted speedup.
AI Software Development – What Does The Data Say?
Industry studies concur on the same trend, observed across hundreds of thousands of code bases and teams over multiple years – undoubtedly AI use increases coding activity very significantly, but that isn’t translating into more value being created. By the time we look at not just what gets shipped, but what gets used, we see no discernible gains.
The effective horizon of agent autonomy decays geometrically with reliability. The more reliable we need the generated code to be, the shorter the horizon. Even with quality gates capable of catching 99% of errors before they propagate and compound, for levels of reliability many of us would consider to be acceptable for release, horizons are extremely short.
[...]
A growing body of research finds a clear correlation between how easy code is for humans to understand and change reliably, and how easy it is for LLMs to do the same. Factors like readability, complexity and duplication have been shown to impact the accuracy of LLM predictions in a similar way to human programmers.
[...]
The energy and compute needed to train an LLM to be an order of magnitude more reliable – e.g., wrong 3% of the time instead of 30% – is 10^20 times what the current frontier models require. Don’t expect significantly more reliable models any time soon. Any future gains in reliability will have to made by better context engineering (deciding what to include in the input) and more effective quality gates deciding what to do with the output- and that’s exactly what we’re seeing AI companies focusing on these days. Models may get more powerful, but not significantly more reliable.
[...]
Verwenden Sie keine AI Assistenten, um sich die Aufgaben lösen zu lassen.
Sie lernen dadurch effektiv nichts!
Die Aufgaben werden immer nur Dinge verlangen, die gelehrt wurden.
In der Klausur/Prüfung steht Ihnen auch kein AI Assistent zur Verfügung.
Programmieren bezeichnet das Formulieren eines Lösungskonzeptes (Algorithmus) in einer Programmiersprache.
Eine präzise Spezifikation von dem was wir wollen/benötigen.
Die Verifikation, dass wir bekommen haben, was wir wollen.
Die Fähigkeit in kleinen Schritten Fortschritt zu machen.
Programmiersprache | Anteil |
|---|---|
Python | 25.98% |
C++ | 8.8% |
C | 8.65% |
Java | 8.35% |
C# | 6.38% |
JavaScript | 3.22% |
Visual Basic | 2.84% |
... | ... |
Programmiersprache | Anteil |
|---|---|
Python | 29.6% |
Java | 14.72% |
C/C++ | 9.27% |
JavaScript | 6.79% |
R | 5.26% |
C# | 4.81% |
Objective-C | 4.17% |
... | ... |
Maschinensprachen (Zahlenkombinationen als Befehle)
(Eine Programmierung in Maschinensprache wird heute nicht mehr durchgeführt.)
Assemblersprachen (wie Maschinensprachen nur besser lesbar)
(Es gibt auch heute noch (vereinzelt) Anwendungsbereiche für Programmierung in Assembler.)
Höhere Programmiersprachen:
Prozedurale Programmiersprachen (z. B. C - noch immer sehr verbreitet)
Objekt-orientierte Programmiersprachen (z. B. C++, Java, ... - sehr verbreitet)
Funktionale Programmiersprachen (z. B. Clojure, F#, ...) - in ausgewählten Anwendungsgebieten
Logische Programmiersprachen (z. B. Prolog - nur noch in (sehr) speziellen Anwendungsgebieten)
Sprachen, die verschiedenste Konzepte unterstützen (z. B. Java, Scala, Kotlin, Python, TypeScript, ... - der aktuelle Standard)
Sprachen für spezielle Anwendungsgebiete (z. B. SQL oder Low-code Ansätze)
(Meist deklarative Sprachen, die für spezielle Anwendungsgebiete entwickelt wurden.)
Bei deklarativen Sprachen beschreibt man nicht wie etwas berechnet wird, sondern was berechnet werden soll. Maschinensprachen und Assemblersprachen sind imperative Sprachen. Höhere Programmiersprachen sind meist imperative Sprachen, aber es gibt auch deklarative Sprachen (insbesondere Prolog bzw. Datalog).
Seit ca. 10 bis 15 Jahren kann man beobachten, dass die Grenzen zwischen den verschiedenen Paradigmen immer mehr verschwimmen und einst rein objekt-orientierte Sprachen auch funktionale Elemente enthalten und umgekehrt.
Sprachen für spezielle Anwendungsgebiete werden auch Domain-specific Languages (DSLs) genannt.
Definition: Algorithmus
Eine exakte, endliche Vorschrift zur schrittweisen Lösung eines (lösbaren) Problems.
Die Beschreibung eines Algorithmus erfolgt mit Hilfe eines wohl definierten Formalismus und ggf. mit Hilfe weiterer (elementarer) Algorithmen.
Es ist zum Beispiel nicht möglich alle reellen Zahlen aufzuzählen - das Problem ist nicht lösbar und es kann kein Algorithmus angegeben werden!
Für eine Eingabe eine bestimmte Eigenschaft feststellen.
Ist eine gegebene Zahl eine Primzahl?
Alle Daten mit einer gegebenen Eigenschaft aufzuzählen.
Zähle alle Primzahlen kleiner als 100 auf!
Eine gegebene Eingabe in eine Ausgabe zu transformieren.
Addition zweier gegebener Zahlen
Mathematisch
natürliche Zahl (inkl. 0)
natürliche Zahl
Java Programm bzw. Skript
1long fak(long n){2if (n == 0) return 1;3else return n * fak(n-1);4}
Ein Algorithmus löst eine Klasse von Problemen. Die konkrete Instanz wird über die Eingabeparameter/Parametrisierung festgelegt.
Die Beschreibung des Algorithmus bzgl. der Verarbeitungsschritte und (Eingabe-)Daten ist endlich und ermöglicht eine Ausführung mit endlichen Ressourcen.
Der Algorithmus führt bei gleichen Eingaben immer zu gleichen Ausgaben.
Der Algorithmus besteht aus einer Folge von elementaren (ausführbaren) Schritte. Diese werden vom Prozessor ausgeführt. Elementare Operationen sind z. B.:
einfache arithmetische Operationen wie Addition, Subtraktion, Division etc.
Vergleiche
Zuweisungen
etc.
Das Ergebnis liegt nach endlich vielen Schritten vor.
(Dies bedeutet aber nicht, dass das Problem auch praktisch lösbar ist.)
Zeit und Platzbedarf sind endlich und in einem gewissen Rahmen abschätzbar.
Normalerweise versucht man den besten, schlechtesten und durchschnittlichen Fall zu bestimmen in Abhängigkeit von der Eingabegröße. (Insbesondere Thema des nächsten Semesters).
Diese Angaben erfolgen unabhängig von einer konkreten Implementierung bzw. Verwendung einer bestimmten Programmiersprache oder Hardware.
Jeder (Teil-)schritt führt bei gleichen Eingaben immer zu gleichen Ausgaben.
Nicht jeder Algorithmus, der die Eigenschaft der Determiniertheit erfüllt, ist auch deterministisch. Bei einem deterministischen Algorithmus führt jeder (Teil-)schritt bei gleichen Eingaben immer zu gleichen Ausgaben, aber dies muss (in bestimmten Fällen) nicht immer erfüllt sein und der Algorithmus kann dennoch determiniert sein.
Insbesondere im Bereich der Kryptographie basieren viele Algorithmen darauf, dass die Ver-/Entschlüsselung nur dann effizient durchführbar ist, wenn man den Schlüssel kennt. Ist der Schlüssel nicht bekannt, dann kann immer noch ein terminierender Algorithmus angegeben werden, der verschlüsselte Daten entschlüsselt, aber dieser ist nicht effizient in sinnvoller Zeit durchführbar.
Die Komplexität eines Algorithmus bestimmt ganz maßgeblich wofür dieser Algorithmus eingesetzt werden kann. Wir können zum Beispiel Algorithmen wie folgt unterscheiden:
konstante Komplexität (d. h. der Algorithmus benötigt unabhängig von der Größe der Eingabe immer gleich lange.)
logarithmische Komplexität
lineare Komplexität
quadratische Komplexität
exponentielle Komplexität (d. h. praktisch nicht anwendbar; häufig sucht man nach alternativen Algorithmen, die auf Heuristiken basieren. Zum Beispiel für das Erfüllbarkeitsproblem (Satisfiability) in der Aussagenlogik.)
Mathematisch (exakt)
reelle Zahl
1BigDecimal e(int steps) {2BigDecimal e = BigDecimal.ZERO;3while (steps >= 0) {4e = e.add(5BigDecimal.ONE.divide(6new BigDecimal(fak(steps)7),8MathContext.DECIMAL128));9steps--;10}11return e;12}
steht hier für die eulersche Zahl.
In diesem Fall wurde folgende Implementierung der Fakultät verwendet:
1import java.math.BigInteger;23BigInteger fak(int n) {4if (n == 0)5return BigInteger.valueOf(1);6else {7var bn = BigInteger.valueOf(n);8return fak(n-1).multiply(bn);9}10}
Schreiben Sie in natürlicher Sprache einen Algorithmus, der eine beliebige natürliche Zahl testet ob diese eine Primzahl ist.
Achten Sie darauf, dass der Algorithmus die vorher diskutierten Eigenschaften erfüllt.
Beschreiben Sie die Komplexität Ihres Algorithmus.
D. h., wie viele Ressourcen (z. B. Rechenschritte) sind in Abhängigkeit von der Eingabe notwendig?
Dienen der Kommunikation zwischen Menschen und sind häufig mehrdeutig.
In vielen Fällen ist die Bedeutung eines Satzes abhängig vom Kontext.
Dienen der eindeutigen Beschreibung von Sachverhalten; sind präzise und eindeutig.
Können ggf. automatisch ausgewertet werden.
Programmiersprachen sind formale Sprachen zur Beschreibung von Algorithmen.
Systemprogrammierung
Anwendungsprogrammierung / Web-Entwicklung
Skriptsprachen
definiert welche Sätze in der Sprache gültig sind. Die Syntax wird durch eine Grammatik formal und präzise beschrieben.
definiert die Bedeutung der Sätze; wenn dies möglich ist. Nicht jeder syntaktisch korrekte Satz hat eine Bedeutung.
Bemerkung
Häufig wird die Semantik „nur“ in einem Standard oder „sogar nur“ durch eine Implementierung festgelegt.
Syntaktisch gültiger Satz:
Sie geht nach Hause.
Syntaktisch gültig, aber semantisch falscher Satz:
Tim schwimmt auf den Mond.
Syntaktisch ungültige Sätze:
Sie fährt nach Hause in die Schule.
Tim geht in die Schule
1Satz = Subjekt WS Prädikat WS Objekt "."2Subjekt = "Tim" | "Sie"3Prädikat = "geht" | "fährt" | "schwimmt" | "fliegt"4Objekt = "nach Hause" | "in die Schule" | "auf den Mond"5WS = " "
Es gibt zahlreiche Varianten der EBNF (Extended Backus-Naur Form). Die grundlegenden Ideen und Konzepte sind jedoch überall gleich.
Beispiele für verschiedene Fehler in Java Programmen
1int fak(long n){2if (n == 0)3return 1l // ';' expected4// ⇒ "Syntaktischer Fehler"5else6return n * fak(n-1);7// incompatible types: possible lossy conversion from long to int8// ⇒ "Semantischer Fehler"9}
Die EBNF dient der Beschreibung kontext-freier Grammatiken.
Verwendung | Notation | Bedeutung |
|---|---|---|
Definition | = | |
Konkatenation | , | |
Terminierung | ; | Ende der Def. |
Alternative | | | |
Optional | [ ... ] | 0 oder 1mal |
Wiederholung | { ... } | 0 oder mehrfach |
Gruppierung | ( ... ) | |
Kommentar | (* ... *) | |
Terminalsymbol | "Terminal" |
Beispiel
Ausdruck =
Ziffer,
{ ("+" | "-"),
Ziffer };
Ziffer =
"1" | "2" | "3" |
"4" | "5" | "6" |
"7" | "8" | "9" |
"0";Die Beschreibung einer Programmiersprache in EBNF besteht aus einer Startregel und einer Menge von weiteren Regeln sowie Terminalen, die die Syntax der Sprache beschreiben. Die Terminalen sind die Basiswörter der Sprache („reservierte Wörter“).
Bei kontext-freien Sprachen kommt auf der linken Seite einer Regel genau ein Nichtterminal vor, auf der rechten Seite können beliebig viele Nichtterminale und Terminale vorkommen.
Was genau „kontext-frei“ bedeutet, ist Gegenstand fortgeschrittener Vorlesungen. Für den Moment reicht es zu wissen, dass dies gewisse Einschränkungen für die Regeln bedeutet. Diese Einschränkungen aber das Verarbeiten zumindest stark vereinfachen und dadurch eine effiziente und eindeutige Verarbeitung ermöglichen.
Binärzahlen in Java
Folgend wird die Syntax von Binärzahlen (BinaryNumeral) in Java beschrieben.[2]
1BinaryNumeral = "0", ("b" | "B"), BinaryDigits2BinaryDigits = BinaryDigit | (BinaryDigit [BinaryDigitsAndUnderscores] BinaryDigit)3BinaryDigit = "0" | "1"4BinaryDigitsAndUnderscores = BinaryDigitOrUnderscore {BinaryDigitOrUnderscore}5BinaryDigitOrUnderscore = BinaryDigit | "_"
Welche der folgenden Zahlen sind gültige Binärzahlen in Java? Falls nicht, warum?
0b1010 0B1010_0
0b1_0_1_0 0B1010_0_
0B_1010 0b1010_0_1
0b1010_ 0_b101Die von der JLS (Java Language Specification) verwendete Syntax wurde hier adaptiert an die zuvor gezeigte Variante. Weitere Änderungen wurden nicht vorgenommen.
EBNF für einfache Ausdrücke
Erweitern Sie die EBNF für mathematische Ausdrücke, um die Möglichkeit Zahlen beliebiger Länge anzugeben und auch Ausdrücke (mathematisch korrekt) zu klammern. D. h. Ihre erweiterte Grammatik soll folgende Ausdrücke zulassen:
12+25
13-4-(4+5)
Bonus
Erweitern Sie die EBNF so, dass auch einfache Fließkommazahlen erlaubt sind (z. B. „1,2“ oder „0,999“). Achten Sie darauf, dass keine ungültigen Zahlen wie „1,“ oder „1,2,3“ erlaubt sind.
Zu installieren (für den Anfang):
Java 27 JDK (Java Development Kit)
https://adoptium.net/en-GB/temurin/releases/?version=27
oder
https://www.azul.com/downloads/?package=jdk#zulu
(Java 24 oder älter ist nicht ausreichend.)
Visual Studio Code, Eclipse Theia, IntelliJ IDEA, ZED oder Eclipse
Achtung!
Deaktivieren bzw. deinstallieren Sie ggf. jegliche KI Assistenten, damit Ihnen die Aufgaben nicht direkt gelöst werden! Alternative können Sie einen einfachen Texteditor mit einfachem Syntaxhighlighting benutzen. (Mac: CotEditor; Windows: Notepad++)