Skip to content
Snippets Groups Projects
Commit b08eb42c authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Vorbereitung 11.10.2021

parent 786f8230
No related branches found
No related tags found
No related merge requests found
Showing
with 2672 additions and 0 deletions
#include <stdio.h>
int main (void)
{
for (int i = 10; i = 0; i - 1)
printf ("%d\n", i);
return 0;
}
20211011/gitlab.png

589 B

File added
\documentclass{article}
\input tmp.inputs
\pagestyle{empty}
\begin{document}
\psscalebox{0.8}{%
\begin{pspicture}(-5,0)(12,12)
\small
\psset{unit=0.5cm}
\psline[arrows=<->](-1,0)(-1,22)
\rput(-1.3,0){\makebox(0,0)[br]{\textbf{gegenständlich}}}
\rput(-1.3,22){\makebox(0,0)[tr]{\textbf{abstrakt}}}
\rput(-1.3,2){\makebox(0,0)[r]{Elektromagnetismus, Halbleiter}}
\rput(-1.3,4){\makebox(0,0)[r]{Elektronische Bauelemente}}
\rput(-1.3,6){\makebox(0,0)[r]{Logik-Schaltkreise}}
\rput(-1.3,8){\makebox(0,0)[r]{Prozessoren}}
\rput(-1.3,9){\makebox(0,0)[r]{Maschinensprache}}
\rput(-1.3,10){\makebox(0,0)[r]{Assembler}}
\rput(-1.3,11){\makebox(0,0)[r]{Ein-/Ausgabe}}
\rput(-1.3,12.35){\makebox(0,0)[r]{\textbf{hardwarenahe Programmierung} (z.\,B.\ in C)}}
\rput(-1.3,14){\makebox(0,0)[r]{\shortstack[r]{abstrahierende Programmierung\\(z.\,B.\ in C++, Java)}}}
% \rput(-1.3,15){\makebox(0,0)[r]{Programmierung}}
\rput(-1.3,16){\makebox(0,0)[r]{Algorithmen, Datenstrukturen, Software-Entwurf}}
\rput(-1.3,17){\makebox(0,0)[r]{Requirements Engineering}}
\rput(-1.3,18){\makebox(0,0)[r]{formale Sprachen, Berechenbarkeit}}
\rput(-1.3,19){\makebox(0,0)[r]{mathematische Strukturen}}
\rput(-1.3,20){\makebox(0,0)[r]{mathematische Beweise}}
\rput(2.1,0.5){\makebox(0,0)[l]{Physik}}
\rput(4.1,4){\makebox(0,0)[l]{Elektrotechnik}}
\rput(6.1,8){\makebox(0,0)[l]{Rechnertechnik}}
\rput(8.1,12.35){\makebox(0,0)[l]{angewandte Informatik}}
\rput(10.1,16){\makebox(0,0)[l]{\shortstack[l]{Softwaretechnik und\\theoretische Informatik}}}
\rput(12.1,21){\makebox(0,0)[l]{Mathematik}}
\psset{linewidth=0.001,linestyle=none,fillstyle=gradient,gradmidpoint=1.0,gradlines=1000}
\definecolor{RGBwhite}{rgb}{1.0,1.0,1.0}
\definecolor{RGBblue}{rgb}{0.0,0.0,1.0}
\definecolor{RGBred}{rgb}{1.0,0.0,0.0}
\definecolor{RGBgreen}{rgb}{0.0,1.0,0.0}
\definecolor{RGByellow}{rgb}{1.0,1.0,0.0}
\definecolor{RGBorange}{rgb}{1.0,0.7,0.0}
\definecolor{RGBgrey}{rgb}{0.7,0.7,0.7}
\rput(0,2){\psframe[gradbegin=RGBwhite,gradend=RGBblue](2,2)}
\rput(0,0){\psframe[fillstyle=solid,fillcolor=RGBblue](2,2.01)}
\rput(2,6){\psframe[gradbegin=RGBwhite,gradend=RGBred](2,2)}
\rput(2,2){\psframe[gradbegin=RGBred,gradend=RGBwhite](2,2)}
\rput(2,3.99){\psframe[fillstyle=solid,fillcolor=RGBred](2,2.02)}
\rput(4,10){\psframe[gradbegin=RGBwhite,gradend=RGBgreen](2,2)}
\rput(4,6){\psframe[gradbegin=RGBgreen,gradend=RGBwhite](2,2)}
\rput(4,7.99){\psframe[fillstyle=solid,fillcolor=RGBgreen](2,2.02)}
\rput(6,14){\psframe[gradbegin=RGBwhite,gradend=RGByellow](2,2)}
\rput(6,10){\psframe[gradbegin=RGByellow,gradend=RGBwhite](2,2)}
\rput(6,11.99){\psframe[fillstyle=solid,fillcolor=RGByellow](2,2.02)}
\rput(8,18){\psframe[gradbegin=RGBwhite,gradend=RGBorange](2,2)}
\rput(8,14){\psframe[gradbegin=RGBorange,gradend=RGBwhite](2,2)}
\rput(8,15.99){\psframe[fillstyle=solid,fillcolor=RGBorange](2,2.02)}
\rput(10,18){\psframe[gradbegin=RGBgrey,gradend=RGBwhite](2,2)}
\rput(10,19.99){\psframe[fillstyle=solid,fillcolor=RGBgrey](2,2.01)}
\end{pspicture}
}
\end{document}
File added
This diff is collapsed.
File added
% hp-2020ws-p1.pdf - Labor Notes on Low-Level Programming
% Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Versuch 1: RSA-Verschlüsselung
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{multicol}
\usepackage{sfmath}
\sloppy
\pagestyle{empty}
\addtolength{\textheight}{1cm}
\newcommand{\sep}{~$\cdot$~}
\newcommand{\mylicense}{CC BY-SA (Version 4.0) oder GNU GPL (Version 3 oder höher)}
\begin{document}
\makebox(0,0.005)[tl]{\includegraphics[scale=0.72]{logo-hochschule-bochum-cvh-text-v2.pdf}}\hfill
\makebox(0,0)[tr]{\includegraphics[scale=0.5]{logo-hochschule-bochum.pdf}}
\par\bigskip\bigskip
\begin{center}
\Large\textbf{Praktikumsversuch 1: RSA-Verschlüsselung}
\par\medskip
\normalsize Hardwarenahe Programmierung\sep
Wintersemester 2021/22\sep
Prof.~Dr.~Peter Gerwinski
\end{center}
Aufgabe: Schreiben Sie ein Programm, das
die Verschlüsselung nach Rivest, Shamir und Adleman (RSA)
sowie die Schwierigkeiten beim Brechen ("`Knacken"') der
Verschlüsselung demonstriert.
\begin{multicols}{2}
Schreiben Sie ein C-Programm (oder mehrere),
das folgendes durchführt:
\begin{itemize}
\item
\textbf{Schlüsselerzeugung}
Bestimmen Sie drei verschiedene Primzahlen $p$, $q$ und $e$, wobei $e$
kleiner als $(\kern0.5pt p-1)\cdot(q-1)$ und teilerfremd zu $(\kern0.5pt p-1)\cdot(q-1)$ sei.
(Dies ist z.\,B.\ der Fall, wenn $e$ größer als $p$ und $q$ ist.)
Berechnen Sie $N = p \cdot q$
sowie eine natürliche Zahl $d$ mit der Eigenschaft:
\begin{displaymath}
(e \cdot d) \,\%\, \bigl((\kern0.5pt p-1)\cdot(q-1)\bigr) = 1
\end{displaymath}
("`$x \,\%\, y\/$"' wird "`x modulo y"' gesprochen und steht
für den Rest, der bei Division von $x$ durch $y$ verbleibt.)
$N$ und $e$ sind der \newterm{öffentliche Schlüssel}. \\
$p$, $q$ und $d$ sind der \newterm{geheime Schlüssel}.
\item
\textbf{Verschlüsselung}
Wählen Sie eine geheime Botschaft $m$ eine Zahl kleiner als $N$,
die Sie verschlüsseln wollen.
$m$ muß teilerfremd zu $N$ sein.
(Dies ist der Fall, wenn $m$ weder durch $p$ noch durch $q$ teilbar ist.)
Schreiben Sie ein Programm, das aus $m$ die verschlüsselte
Nachricht $c$ berechnet:
\begin{displaymath}
c = m^e ~\%\, N
\end{displaymath}
\textbf{Hinweis:}
\begin{displaymath}
m^e ~\%\, N
= \underbrace{(m \cdot m \cdot \dots \cdot m)}_{\mbox{$e$ Faktoren}} \,\%\, N
\hspace*{2cm}
\end{displaymath}
\vspace*{-\medskipamount}
\begin{displaymath}
= \underbrace{\Bigl(\dots\bigl((m \cdot m) \,\%\, N \cdot m\bigr) \,\%\, N \cdot \dots \cdot m\Bigr) \,\%\, N}_{\mbox{$e$ Faktoren}}
\end{displaymath}
Dies bedeutet: Multiplizieren Sie die Zahl $m$ $e$-mal mit sich selbst,
wobei Sie \emph{nach jeder Multiplikation\/} modulo $N$ rechnen.
\item
\textbf{Entschlüsselung}
Rekonstruieren Sie aus der verschlüsselten Botschaft $c$
wieder die geheime Botschaft $m$:
\begin{displaymath}
m = c^d ~\%\, N
\end{displaymath}
\item
\textbf{Verschlüsselung brechen}
Rekonstruieren Sie aus der verschlüsselten Botschaft $c$
wieder die geheime Botschaft $m$,
\emph{ohne\/} den geheimen Schlüssel zu kennen,
d.\,h.\ Sie kennen nur $N$ und $e$, nicht jedoch $p$, $q$ und $d$.
\textbf{Hinweis:}
Sie können z.\,B.\ versuchen, $N$ in seine Primfaktoren zu zerlegen.
Auf diese Weise können Sie zunächst $p$ und $q$ berechnen und danach $d$.
\item
\textbf{Rechenzeit vergleichen}
Vergleichen Sie nun
die für das Brechen der Verschlüsselung benötigte Rechenzeit
mit der Zeit, die das reguläre Ver- und Entschlüsseln dauert.
(Auf diesem Schwierigkeitsunterschied
beruht die Sicherheit der RSA-Verschlüsselung.)
\textbf{Hinweis 1:}
% Wenn Sie ein Programm per Kommandozeile mit \lstinline[style=cmd]{time ./programm} starten,
% wird Ihnen angezeigt, wieviel Rechenzeit das Programm benötigt hat.
% Die drei angezeigten Werte stehen hierbei für die
% tatsächlich verstrichene Gesamtzeit (\lstinline[style=terminal]{real}),
% für die mit Rechnen verbrachte Zeit (\lstinline[style=terminal]{user})
% und für die mit Systemaufrufen (z.\,B.\ Ein- und Ausgabe)
% verbrachte Zeit (\lstinline[style=terminal]{sys}).
Ein einfacher Weg, die von Ihrem Programm benötigte Rechenzeit zu messen,
ist die Verwendung der Funktion \lstinline{clock()}.
Diese gibt zurück, wieviel Rechenzeit seit Programmstart aufgewendet wurde.
Der Typ dieses Rückgabewerts ist ein ganzzahliger Typ, \lstinline{clock_t},
mit dem man rechnen und den man mit \lstinline{%ld} ausgeben kann.
Pro Sekunde wächst der Zähler um \lstinline{CLOCKS_PER_SEC} Einheiten.
Typischerweise hat \lstinline{CLOCKS_PER_SEC} den Wert \lstinline{1000000}
oder \lstinline{1000}, die Zeiteinheit ist also eine Mikrosekunde
bzw.\ eine Millisekunde.
\textbf{Hinweis 2:}
Die mit der o.\,a.\ Methode meßbaren Zeiten sind eigentlich zu ungenau,
um damit die sehr kurzen Rechenzeiten erfassen zu können --
etwa so, als wollten Sie mit einem Lineal mit Millimetereinteilung
die Dicke eines Blatts Papier messen. Beides ist jedoch möglich.
\item
\textbf{Abgabe:}
Ihre Quelltexte mit den Lösungen der Praktikumsaufgabe schicken Sie bitte
per E-Mail an \file{peter.gerwinski@hs-bochum.de}
mit dem \textbf{Betreff:} \lstinline[style=terminal]{eiT2ieNo}
unter Angabe von Name, Matrikel-Nummer,
Studiengang (MI/MP/TI) und Studienmodell (KIA/KIS/GS).
\end{itemize}
\end{multicols}
\vspace*{-\bigskipamount}
\strut\hfill\emph{Viel Erfolg!}
\vfill
\begingroup
\small
\setlength{\leftskip}{3cm}
Stand: 11.\ Oktober 2021
% Soweit nicht anders angegeben:\\
Copyright \copyright\ 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021\quad Peter Gerwinski\\
Lizenz: \mylicense
Sie können diese Praktikumsunterlagen einschließlich \LaTeX-Quelltext
%% und Beispielprogramme\\
herunterladen unter:\\
\url{https://gitlab.cvh-server.de/pgerwinski/hp}
\endgroup
\end{document}
File added
% hp-musterloesung-20211011.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 11.\ Oktober 2021}
\exercise{Schaltjahr ermitteln}
Schreiben Sie ein C-Programm, das eine Jahreszahl erfragt
und ausgibt, ob es sich um ein Schaltjahr handelt.
\begin{itemize}
\item Wenn die Jahreszahl durch 4 teilbar ist, ist das Jahr zunächst einmal ein Schaltjahr.
\item Ausnahme: Wenn die Jahreszahl durch 100 teilbar ist, ist das Jahr kein Schaltjahr.
\item Ausnahme von der Ausnahme: Wenn die Jahreszahl durch 400 teilbar ist,\\
ist das Jahr doch wieder ein Schaltjahr.
\end{itemize}
\solution
Am einfachsten ist es, die Aufgabenstellung in geschachtelte
\lstinline{if}-Verzweigungen zu übersetzen.
Im folgenden finden Sie eine Funktion \lstinline{is_leap_year()},
der man das Jahr übergibt und die für Schaltjahre \lstinline{1}
zurückgibt und für Nicht-Schaltjahre \lstinline{0}.
\begin{lstlisting}
#include <stdio.h>
int is_leap_year (int year)
{
int leap_year = 0;
if (year % 4 == 0)
{
leap_year = 1;
if (year % 100 == 0)
{
leap_year = 0;
if (year % 400 == 0)
leap_year = 1;
}
}
return leap_year;
}
\end{lstlisting}
(In C steht \lstinline{0} für den Wahrheitswert "`falsch"'
und jeder Wert ungleich \lstinline{0} für den Wahrheitswert "`wahr'";
die Zeile \lstinline{leap_year = 0} steht daher wörtlich und
selbsterklärend für "`ist kein Schaltjahr"'.)
Unter Verwendung von \lstinline{else} läßt sich dies verkürzen zu:
\begin{lstlisting}
#include <stdio.h>
int is_leap_year (int year)
{
if (year % 4 == 0)
{
if (year % 100 == 0)
{
if (year % 400 == 0)
return 1;
else
return 0;
}
else
return 1;
}
else
return 0;
}
\end{lstlisting}
Eine andere Möglichkeit ist es, die Schaltjahr-Bedingung in eine
Kette von "`und"'- und "`oder"'-Verknüpfungen
(C-Operatoren \lstinline{&&} und \lstinline{||}) zu übersetzen:
\begin{lstlisting}
int is_leap_year (int year)
{
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
return 1;
else
return 0;
}
\end{lstlisting}
Dies ist zwar kürzer, aber nicht unbedingt übersichtlicher.
Der erzeugte Code ist übrigens \emph{nicht\/} kürzer und/oder
effizienter als bei der Verwendung mehrerer
\lstinline{if}-Verzweigungen.
Wir empfehlen, daß Sie immer so programmieren,
daß Sie selbst den maximalen Überblick über Ihr Programm behalten.
\goodbreak
Ein Hauptprogramm, das die o.\,a.\ Funktion aufruft,
könnte dann wie folgt aussehen:
\begin{lstlisting}
int main (void)
{
int year;
printf ("Bitte geben Sie eine Jahreszahl ein: ");
scanf ("%d", &year);
if (is_leap_year (year))
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
return 0;
}
\end{lstlisting}
In den Dateien \gitfile{hp}{2021ws/20211011}{loesung-1-1.c} bis \gitfile{hp}{2021ws/20211011}{loesung-1-3.c}
finden Sie lauffähige Programme, die die o.\,a.\ Funktionen aufrufen.
Beachten Sie, daß die Funktion \emph{vor\/} dem Hauptprogramm
deklariert werden muß, damit das Hauptprogramm sie kennt.
(Es gibt Tricks, mit denen es auch anders geht,
aber was hätten wir in diesem Zusammenhang davon?)
In \gitfile{hp}{2021ws/20211011}{loesung-1-4.c} und \gitfile{hp}{2021ws/20211011}{loesung-1-5.c}
findet die Schaltjahr-Prüfung direkt im Hauptprogramm statt.
Dies ist ebenfalls eine richtige Lösung der Aufgabe,
schränkt aber die Wiederverwertbarkeit des Codes ein.
Die Datei \gitfile{hp}{2021ws/20211011}{loesung-1-4.c} enthält darüberhinaus Codeverdopplungen,
nämlich mehrere identische \lstinline{printf()}-Auf"-rufe
an unterschiedlichen Stellen.
Dies ist schlechter Programmierstil ("`Cut-and-paste-Programmierung"').
Die besten Lösungen sind \gitfile{hp}{2021ws/20211011}{loesung-1-2.c}
und \gitfile{hp}{2021ws/20211011}{loesung-1-3.c}.
\goodbreak
Zum Testen:\vspace*{-\medskipamount}
\begin{itemize}\itemsep0pt
\item 1900 ist kein Schaltjahr.
\item 1902 ist kein Schaltjahr.
\item 1904 ist ein Schaltjahr.
\item 1996 ist ein Schaltjahr.
\item 1998 ist kein Schaltjahr.
\item 2000 ist ein Schaltjahr.
\item 2002 ist kein Schaltjahr.
\item 2004 ist ein Schaltjahr.
\item 2018 ist kein Schaltjahr.
\item 2019 ist kein Schaltjahr.
\item 2020 ist ein Schaltjahr.
\item 2021 ist kein Schaltjahr.
\end{itemize}
\goodbreak
Hier noch ein Hinweis für Unix-Shell-Experten:
\begin{lstlisting}[style=cmd]
for y in 1 2 3 4 5; do
clear
for x in 1900 1902 1904 1996 1998 2000 2002 2004 2018 2019 2020 2021; do
echo $x | ./loesung-1-$y
done
sleep 2s
done
\end{lstlisting}
\exercise{Multiplikationstabelle}
Geben Sie mit Hilfe einer Schleife ein "`Einmaleins"' aus.\\
Dabei sollen die Faktoren und Ergebnisse rechtsbündig untereinander stehen:
\begin{lstlisting}[style=terminal]
1 * 7 = 7
2 * 7 = 14
...
10 * 7 = 70
\end{lstlisting}
Hinweis: Verwenden Sie Formatspezifikationen wie z.\,B.\ \lstinline{%3d}\\
(siehe dazu die Dokumentation zu \lstinline{printf()},
z.\,B.\ \,\lstinline[style=cmd]{man 3 printf}\,)
\solution
Drei verschiedene richtige Lösungen finden Sie in den Dateien
\gitfile{hp}{2021ws/20211011}{loesung-2-1.c}, \gitfile{hp}{2021ws/20211011}{loesung-2-2.c} und \gitfile{hp}{2021ws/20211011}{loesung-2-3.c}.
(Zum Compilieren von \gitfile{hp}{2021ws/20211011}{loesung-2-2.c} und \gitfile{hp}{2021ws/20211011}{loesung-2-3.c}
ist mindestens der C99-Standard erforderlich; bitte nötigenfalls
in \file{gcc} die Option \lstinline[style=cmd]{-std=c99} mit angeben.)
Die Lösung in \gitfile{hp}{2021ws/20211011}{loesung-2-3.c} ist zwar richtig,
aber unnötig kompliziert und daher nicht empfohlen.
Eine \textbf{falsche} Lösung finden Sie in der Datei \gitfile{hp}{2021ws/20211011}{loesung-2-f4.c}:
In der Ausgabe dieses Programms stehen die Faktoren und Ergebnisse
nicht rechtsbündig untereinander.
\exercise{Fibonacci-Zahlen}
Die Folge der Fibonacci-Zahlen ist definiert durch:
\begin{quote}
1.\ Zahl: 0\\
2.\ Zahl: 1\\
nächste Zahl = Summe der beiden vorherigen
\end{quote}
Schreiben Sie ein Programm, das die ersten 50 Fibonacci-Zahlen ausgibt.
Falls Ihnen dabei irgendwelche Besonderheiten auffallen
und/oder Sie irgendwelche besondere Maßnahmen treffen,
dokumentieren Sie diese.
(Wem dies zu einfach ist, kann auch gerne
die ersten 100 Fibonacci-Zahlen ausgeben.)
\solution
Zwei verschiedene richtige Lösungen finden Sie in den Dateien
\gitfile{hp}{2021ws/20211011}{loesung-3-1.c} und \gitfile{hp}{2021ws/20211011}{loesung-3-2.c}.
Die Lösung in \gitfile{hp}{2021ws/20211011}{loesung-3-2.c}
speichert alle berechneten Zahlen in einem Array,
die in \gitfile{hp}{2021ws/20211011}{loesung-3-1.c} hingegen
speichert immer nur maximal drei Zahlen gleichzeitig.
Sofern nicht alle berechneten Zahlen später noch benötigt werden,
ist daher \gitfile{hp}{2021ws/20211011}{loesung-3-1.c} zu bevorzugen.
Wichtig in \gitfile{hp}{2021ws/20211011}{loesung-3-1.c} ist, daß \lstinline{f0 + f1} berechnet wird,
\emph{bevor\/} \lstinline{f0} oder \lstinline{f1} ein neuer Wert zugewiesen wird.
Dies ist nur möglich, weil das Programm
eine zusätzliche Variable (hier: \lstinline{f2}) verwendet.
\goodbreak
Eine "`Besonderheit"' besteht darin, daß das Ergebnis
ab der Fibonacci-Zahl Nr.~47 \textbf{falsch} ist:
\begin{lstlisting}[style=terminal]
f[45] = 1134903170
f[46] = 1836311903
f[47] = -1323752223
f[48] = 512559680
f[49] = -811192543
\end{lstlisting}
Die Summe zweier positiver Zahlen darf keine negative Zahl sein.
(Mit der Dokumentation dieser Beobachtung
ist die Aufgabenstellung bereits erfüllt.)
Der Grund für diese fehlerhafte Rechnung
ist die begrenzte Rechengenauigkeit unserer Rechner,
in diesem Fall ein sogenannter \newterm{Integer-Überlauf}.
Details dazu sind Gegenstand von Kapitel~5 der Lehrveranstaltung.
Eine "`besondere Maßnahme"' besteht darin,
anstelle des "`normalen"' Ganzzahl-Datentyps \lstinline{int}
"`lange"' ganze Zahlen (\lstinline{long int}) zu verwenden --
siehe \gitfile{hp}{2021ws/20211011}{loesung-3-3.c}.
Damit nicht nur die Rechnung, sondern auch die Ausgabe funktioniert,
muß die Formatspezifikation in \lstinline{printf()}
von \lstinline{%d} zu \lstinline{%ld} angepaßt werden --
siehe \gitfile{hp}{2021ws/20211011}{loesung-3-4.c}.
(Anstelle von \lstinline{long int} verwendet man üblicherweise
abkürzend \lstinline{long} -- siehe \gitfile{hp}{2021ws/20211011}{loesung-3-5.c}.)
Wenn die genaue Rechengenauigkeit wichtig ist, sind die Definitionen
der Datentypen \lstinline{int} und \lstinline{long} zu unpräzise.
Für derartige Fälle gibt es spezielle Datentypen,
z.\,B.\ \lstinline{uint64_t} für vorzeichenlose 64-Bit-Ganzzahlen.
Für die Ausgabe derartiger Datentypen sind spezielle Formatspezifikationen
erforderlich. Die Beispiel-Lösungen \gitfile{hp}{2021ws/20211011}{loesung-3-5.c}
und \gitfile{hp}{2021ws/20211011}{loesung-3-6.c} funktionieren zwar,
zeigen aber \emph{noch nicht\/} die bestmögliche Lösung.
\textbf{Achtung:} Die Verwendung von Fließkommazahlen
für ganzzahlige Berechnungen wie bei den Fibonacci-Zahlen
ist \textbf{nicht} zielführend!
Die in \gitfile{hp}{2021ws/20211011}{loesung-3-7f.c}
bis \gitfile{hp}{2021ws/20211011}{loesung-3-12f.c} vorgestellte "`Lösung"'
ist \textbf{falsch}.
\bigskip
\exercise{Fehlerhaftes Programm}
\begin{minipage}[t]{0.65\textwidth}
Wir betrachten das nebenstehende C-Programm
(Datei: \gitfile{hp}{2021ws/20211011}{aufgabe-4.c}).
\begin{itemize}
\item[(a)]
Was bewirkt dieses Programm? Begründen Sie Ihre Antwort.
Schreiben Sie Ihre Begründung so auf,
daß man sie auch dann versteht,
wenn man gerade nicht die Möglichkeit hat,
bei Ihnen persönlich nachzufragen
(z.\,B.\ weil man gerade eine Klausur korrigiert).
Die Schwierigkeit dieser Aufgabe besteht
nicht allein darin, die Problematik zu verstehen,
sondern auch darin, dieses Verständnis für andere aufzuschreiben.
\item[(b)]
Ändern Sie das Programm so um,
daß es einen "`Countdown"' von 10 bis 0 ausgibt.
\end{itemize}
\end{minipage}\hfill
\begin{minipage}[t]{0.3\textwidth}
\begin{lstlisting}[gobble=6]
#include <stdio.h>
int main (void)
{
for (int i = 10; i = 0; i - 1)
printf ("%d\n", i);
return 0;
}
\end{lstlisting}
\end{minipage}
\solution
\begin{itemize}
\item[(a)]
\textbf{Was bewirkt dieses Programm? Begründen Sie Ihre Antwort.}
Dieses Programm bewirkt nichts.
Die \lstinline{for}-Schleife wird nicht ausgeführt.
Begründung: Die \lstinline{for}-Bedingung ist eine Zuweisung
des Werts \lstinline{0} an die Variable \lstinline{i}.
Neben dem Seiteneffekt der Zuweisung liefert der Ausdruck
einen Wert zurück, nämlich den zugewiesenen Wert
\lstinline{0}. Dieser wird von \lstinline{for} als eine
Bedingung mit dem konstanten Wert "`falsch"' interpretiert.
(Hinweis: Ohne diese Begründung ist die Aufgabe nur zu einem
kleinen Teil gelöst.)
Darüberhinaus ist die Zähl-Anwendung unwirksam: Sie berechnet
den Wert \lstinline{i - 1} und vergißt ihn wieder, ohne ihn
einer Variablen (z.\,B.\ \lstinline{i}) zuzuweisen.
\goodbreak
\item[(b)]
\textbf{Ändern Sie das Programm so, daß es einen "`Countdown"' von 10 bis 0 ausgibt.}
Datei \gitfile{hp}{2021ws/20211011}{loesung-4.c}:
\begin{lstlisting}[gobble=8]
#include <stdio.h>
int main (void)
{
for (int i = 10; i >= 0; i--)
printf ("%d\n", i);
return 0;
}
\end{lstlisting}
\end{itemize}
\end{document}
File added
% hp-uebung-20211011.pdf - Exercises on Low-Level Programming / Applied Computer Sciences
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
\thispagestyle{empty}
\section*{Hardwarenahe Programmierung\\
Übungsaufgaben -- 11.\ Oktober 2021}
\exercise{Schaltjahr ermitteln}
Schreiben Sie ein C-Programm, das eine Jahreszahl erfragt
und ausgibt, ob es sich um ein Schaltjahr handelt.
\begin{itemize}
\item Wenn die Jahreszahl durch 4 teilbar ist, ist das Jahr zunächst einmal ein Schaltjahr.
\item Ausnahme: Wenn die Jahreszahl durch 100 teilbar ist, ist das Jahr kein Schaltjahr.
\item Ausnahme von der Ausnahme: Wenn die Jahreszahl durch 400 teilbar ist,\\
ist das Jahr doch wieder ein Schaltjahr.
\end{itemize}
\exercise{Multiplikationstabelle}
Geben Sie mit Hilfe einer Schleife ein "`Einmaleins"' aus.\\
Dabei sollen die Faktoren und Ergebnisse rechtsbündig untereinander stehen:
\begin{lstlisting}[style=terminal]
1 * 7 = 7
2 * 7 = 14
...
10 * 7 = 70
\end{lstlisting}
\textbf{Hinweis:} Verwenden Sie Formatspezifikationen wie z.\,B.\ \lstinline{%3d}\\
(siehe dazu die Dokumentation zu \lstinline{printf()},
z.\,B.\ \,\lstinline[style=cmd]{man 3 printf}\,)
\exercise{Fibonacci-Zahlen}
Die Folge der Fibonacci-Zahlen ist definiert durch:
\begin{quote}
1.\ Zahl: 0\\
2.\ Zahl: 1\\
nächste Zahl = Summe der beiden vorherigen
\end{quote}
Schreiben Sie ein Programm, das die ersten 50 Fibonacci-Zahlen ausgibt.
Falls Ihnen dabei irgendwelche Besonderheiten auffallen
und/oder Sie irgendwelche besondere Maßnahmen treffen,
dokumentieren Sie diese.
(Wem dies zu einfach ist, kann auch gerne
die ersten 100 Fibonacci-Zahlen ausgeben.)
\exercise{Fehlerhaftes Programm}
\begin{minipage}[t]{0.65\textwidth}
Wir betrachten das nebenstehende C-Programm
(Datei: \gitfile{hp}{2021ws/20211011}{aufgabe-4.c}).
\begin{itemize}
\item[(a)]
Was bewirkt dieses Programm? Begründen Sie Ihre Antwort.
Schreiben Sie Ihre Begründung so auf,
daß man sie auch dann versteht,
wenn man gerade nicht die Möglichkeit hat,
bei Ihnen persönlich nachzufragen
(z.\,B.\ weil man gerade eine Klausur korrigiert).
Die Schwierigkeit dieser Aufgabe besteht
nicht allein darin, die Problematik zu verstehen,
sondern auch darin, dieses Verständnis für andere aufzuschreiben.
\item[(b)]
Ändern Sie das Programm so um,
daß es einen "`Countdown"' von 10 bis 0 ausgibt.
\end{itemize}
\end{minipage}\hfill
\begin{minipage}[t]{0.3\textwidth}
\begin{lstlisting}[gobble=6]
#include <stdio.h>
int main (void)
{
for (int i = 10; i = 0; i - 1)
printf ("%d\n", i);
return 0;
}
\end{lstlisting}
\end{minipage}
\end{document}
#include <stdio.h>
int is_leap_year (int year)
{
int leap_year = 0;
if (year % 4 == 0)
{
leap_year = 1;
if (year % 100 == 0)
{
leap_year = 0;
if (year % 400 == 0)
leap_year = 1;
}
}
return leap_year;
}
int main (void)
{
int year;
printf ("Bitte geben Sie eine Jahreszahl ein: ");
scanf ("%d", &year);
if (is_leap_year (year))
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
return 0;
}
#include <stdio.h>
int is_leap_year (int year)
{
if (year % 4 == 0)
{
if (year % 100 == 0)
{
if (year % 400 == 0)
return 1;
else
return 0;
}
else
return 1;
}
else
return 0;
}
int main (void)
{
int year;
printf ("Bitte geben Sie eine Jahreszahl ein: ");
scanf ("%d", &year);
if (is_leap_year (year))
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
return 0;
}
#include <stdio.h>
int is_leap_year (int year)
{
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
return 1;
else
return 0;
}
int main (void)
{
int year;
printf ("Bitte geben Sie eine Jahreszahl ein: ");
scanf ("%d", &year);
if (is_leap_year (year))
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
return 0;
}
#include <stdio.h>
int main (void)
{
int year;
printf ("Bitte geben Sie eine Jahreszahl ein: ");
scanf ("%d", &year);
if (year % 4 == 0)
{
if (year % 100 == 0)
{
if (year % 400 == 0)
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
}
else
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
}
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
return 0;
}
#include <stdio.h>
int main (void)
{
int year;
printf ("Bitte geben Sie eine Jahreszahl ein: ");
scanf ("%d", &year);
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
printf ("Das Jahr %d ist ein Schaltjahr.\n", year);
else
printf ("Das Jahr %d ist kein Schaltjahr.\n", year);
return 0;
}
#include <stdio.h>
int main (void)
{
int a = 1;
int b = 7;
while (a <= 10)
{
printf ("%2d * %d = %2d\n", a, b, a * b);
a++;
}
return 0;
}
#include <stdio.h>
int main (void)
{
int x = 7;
for (int i = 1; i <= 10; i++)
printf ("%2d *%2d =%3d\n", i, x, i * x);
return 0;
}
#include <stdio.h>
int main (void)
{
int x = 7;
for (int i = 1; i <= 10; i++)
{
if (i >= 10)
printf ("%d", i);
else
printf (" %d", i);
printf (" * %d = ", x);
int y = i * x;
if (y >= 10)
printf ("%d", y);
else
printf (" %d", y);
printf ("\n");
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment