{ "cells": [ { "cell_type": "markdown", "id": "caf638c6", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ " # Datentypen und Genauigkeit\n", "#### Marcel Lüthi, Patrick Schnider
Departement Mathematik und Informatik, Universität Basel" ] }, { "cell_type": "markdown", "id": "8a90fd16", "metadata": { "deletable": false, "slideshow": { "slide_type": "fragment" } }, "source": [ "In diesem Notebook schauen wir uns vier grundlegende Datentypen von Java an. Sie lernen:\n", "- den Wertebereich der Datentypen.\n", "- wie Sie die Datentypen zwischeneinander konvertieren können.\n", "- was Sie beachten müssen wenn es um die Genauigkeit geht." ] }, { "cell_type": "markdown", "id": "d0bc709d", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ "### Datentypen für ganze Zahlen und Gleitkommazahlen" ] }, { "cell_type": "markdown", "id": "d3905f84", "metadata": { "deletable": false, "slideshow": { "slide_type": "skip" } }, "source": [ "Sie haben den Unterschied zwischen ganzen Zahlen und Gleitkommazahlen in Java kennen gelernt. Dafür haben Sie bisher `int` und `double` verwendet. In Java gibt es aber noch den Datentpen `long` für ganze Zahlen, dessen Wertebereich grösser ist als der von `int`. Bei den Gleitkommazahlen gibt es noch den Datentypen `float`, welche die Zahlen weniger genau darstellt als `double`." ] }, { "cell_type": "markdown", "id": "9020e00c", "metadata": { "deletable": false, "slideshow": { "slide_type": "fragment" } }, "source": [ "Entscheidungskriterien\n", "- Ganze Zahlen `int`. Verwenden Sie `long` wenn der Wertebereich von `int` nicht gross genug ist.\n", "- Gleitkommazahlen `double`. Verwenden Sie`float` wenn der Speicher zu begrenzt ist.\n", "- (Nicht in der Vorlesung `byte` und `short`, welche ganze Zahlen nur in einem kleineren Bereich als `int` darstellen können.)" ] }, { "cell_type": "markdown", "id": "6e852873", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "Um einen Zahlwert als `long` zu kennzeichnen, folgt nach der ganzen Zahl der Buchstabe `l` (kleines `L`).\n", "```java\n", "1l\n", "9876543210l\n", "```\n", "Um einen Zahlenwert als `float` zu kennzeichnen, folgt nach dem Zahlwert der Buchstabe `f`.\n", "```java\n", "1f\n", "-2.345f\n", "3.1415e-3f\n", "```" ] }, { "cell_type": "markdown", "id": "1b5f72a1", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Miniübung\n", "- Initialisieren Sie je eine Variable von Typ `long` und `float`.\n", "- Weisen Sie die Variable vom Typ `float` einer Variable vom Typ `double` zu.\n", "- Weisen Sie die Variable vom Typ `long` einer Variable vom Typ `int` zu.\n", "- Was beobachten Sie?" ] }, { "cell_type": "code", "execution_count": null, "id": "aa02e1b2", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class Values {\n", " public static void main(String[] args) {\n", " // Ihre Lösung kommt hier hin\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "578f8405", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "Values.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "872f0d88", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Ordnung der Datentypen" ] }, { "cell_type": "markdown", "id": "66f9d921", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Auf den Wertebereiche der Datentypen bezogen gilt:\n", "$$ int \\subset long \\subset float \\subset double$$\n", "\n", "In Java ist die Zuweisung eines Wertes an eine Variable des gleichen oder *mächtigeren* Datentyps erlaubt." ] }, { "cell_type": "markdown", "id": "f3fb5d9a", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Wertebereich" ] }, { "cell_type": "markdown", "id": "f2f1e602", "metadata": { "deletable": false, "slideshow": { "slide_type": "skip" } }, "source": [ "In Java gibt es definierte Konstanten welche den Wertebereich der jeweiligen Datentypen angeben.\n", "\n", "Vorsicht: Die Konstanten mit dem selben Namen können für unterschiedliche Typen etwas anderes bedeuten. Dies könnte ein Hinweis auf nicht so guten Programmierstil sein." ] }, { "cell_type": "markdown", "id": "2aec92ac", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Konstanten welche den Wertebereich angeben sind:\n", "\n", "| Typ | Konstante | Bedeutung |\n", "| --- | --- | --- |\n", "| int | Integer.MAX_VALUE | grösster, darstellbarer Wert |\n", "| int | Integer.MIN_VALUE | kleinster, darstellbarer Wert |\n", "| long | Long.MAX_VALUE | grösster, darstellbarer Wert |\n", "| long | Integer.MIN_VALUE | kleinster, darstellbarer Wert |\n", "| float | Float.MAX_VALUE | grösster, darstellbarer Wert |\n", "| float | Float.MIN_VALUE | kleinster, positiver, darstellbarer Wert |\n", "| double | Double.MAX_VALUE | grösster, darstellbarer Wert |\n", "| double | Double.MIN_VALUE | kleinster, positiver, darstellbarer Wert |\n", "\n", "
\n", " Das Minimum der darstellbaren Gleitkommazahlen finden Sie als das negierte Maximum.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "d03fbe63", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class Range {\n", " public static void main(String[] args) {\n", " System.out.println(\"int stellt Zahlen von \" +\n", " Integer.MIN_VALUE + \" bis \" +\n", " Integer.MAX_VALUE + \" dar.\");\n", " System.out.println(\"Dies ist in etwa +- 2 Milliarden.\");\n", " System.out.println(\"long stellt Zahlen von \" +\n", " Long.MIN_VALUE + \" bis \" +\n", " Long.MAX_VALUE + \" dar.\");\n", " System.out.println(\"Dies ist in etwa +- 9 Trillionen.\");\n", " System.out.println(\"float stellt Zahlen von \" +\n", " (-Float.MAX_VALUE) + \" bis \" +\n", " Float.MAX_VALUE + \" dar.\");\n", " System.out.println(\"double stellt Zahlen von \" +\n", " (-Double.MAX_VALUE) + \" bis \" +\n", " Double.MAX_VALUE + \" dar.\");\n", " \n", " System.out.println(Float.MIN_VALUE + \" ist nur etwas grösser als 0.0f.\");\n", " System.out.println(Double.MIN_VALUE + \" ist nur etwas grösser als 0.0.\");\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "156ab919", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "Range.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "c55cdbb5", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Welches ist der richtige Typ?" ] }, { "cell_type": "markdown", "id": "e6a97345", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Welchen der vier Typen würden Sie bei den folgenden Aufgabenstellungen verwenden?\n", "- \"Speichern Sie den Geldbetrag eines Bankkunden.\"\n", "- \"Speichern Sie das Gewicht einer Person.\"\n", "- \"Zählen Sie die Häuser in der Stadt Basel.\"\n", "- \"Speichern Sie die Eulersche Zahl.\"\n", "- \"Zählen Sie alle Menschen auf dieser Erde.\"" ] }, { "cell_type": "markdown", "id": "d50369bf", "metadata": { "deletable": false, "slideshow": { "slide_type": "skip" } }, "source": [ "Für diesen Kurs gilt in der Regel: Wenn nichts spezielles steht, nehmen Sie entweder `double` oder `int`. Dabei verwenden wir `double` für Messgrössen und `int` für Zählgrössen." ] }, { "cell_type": "markdown", "id": "f43f13d8", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Speicherbedarf" ] }, { "cell_type": "markdown", "id": "90f3362d", "metadata": { "deletable": false, "slideshow": { "slide_type": "skip" } }, "source": [ "Der Speicherbedarf wird gemessen, indem man die zum Speichern benötigten Bits, also die Anzahl Nullen und Einsen, angibt. Den Speicherbedarf können Sie für `int`, `long`, `float` und `double` mit Hilfe von in Java definierten Konstanten heraus finden." ] }, { "cell_type": "markdown", "id": "3eae7a62", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Die Konstanten welche den Speicherbedarf angeben sind:\n", "\n", "| Typ | Konstante |\n", "| --- | --- |\n", "| int | Integer.SIZE |\n", "| long | Long.SIZE |\n", "| float | Float.SIZE |\n", "| double | Double.SIZE |\n" ] }, { "cell_type": "code", "execution_count": null, "id": "0f273add", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class MemoryFootprint {\n", " public static void main(String[] args) {\n", " System.out.println(\"int belegt \" + Integer.SIZE + \" Bits im Speicher.\");\n", " System.out.println(\"long belegt \" + Long.SIZE + \" Bits im Speicher.\");\n", " System.out.println(\"float belegt \" + Float.SIZE + \" Bits im Speicher.\");\n", " System.out.println(\"double belegt \" + Double.SIZE + \" Bits im Speicher.\");\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "1cc95a36", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "MemoryFootprint.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "39233d2f", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ "### Konstanten" ] }, { "cell_type": "markdown", "id": "884a1e6e", "metadata": { "deletable": false, "slideshow": { "slide_type": "fragment" } }, "source": [ "Variablen die ihren Wert nicht ändern sollen können mit dem Schlüsselwort `final` gekennzeichnet werden.\n", "\n", "Beispiele:\n", "- physikalische oder mathematische Konstanten\n", "- unveränderbare Werte in einem Programm (z.B. Serveradresse, Programmname)\n", "\n", "Namenskonvention: `ALL_CAPITAL_LETTERS`" ] }, { "cell_type": "code", "execution_count": null, "id": "e1446dd7", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class ConstantValues {\n", " public static void main(String[] args) {\n", " final int MAX_LENGTH = 12;\n", " System.out.println(MAX_LENGTH + \" und \" + Math.PI + \" sind Werte von Konstanten.\");\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "370a8ed5", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "ConstantValues.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "3b75be9b", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "##### Miniübung\n", "- Versuchen Sie der Konstanten in der Zelle oben einen neuen Wert zuzuweisen." ] }, { "cell_type": "markdown", "id": "8db0a4dd", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ "### Rechenaufgabe" ] }, { "cell_type": "markdown", "id": "a5d53be6", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Berechnen Sie die Lösung für die folgende Aufgabe und geben Sie die Zahl aus.\n", "- Sie wollen einen Gartenzaun der Länge 20m bauen.\n", "- Ein Element hat die Länge 1.48m.\n", "- Geben Sie aus wieviele Elemente Sie kaufen müssen." ] }, { "cell_type": "code", "execution_count": null, "id": "54ef7d43", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class GardenFence {\n", " public static void main(String[] args) {\n", " // Ihre Lösung kommt hier hin\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "b2217216", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "GardenFence.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "f0810e84", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ "### Type-Casting" ] }, { "cell_type": "markdown", "id": "e7f4826f", "metadata": { "deletable": false, "slideshow": { "slide_type": "skip" } }, "source": [ "Beim Type-Casting schreibt man den Typ der Variablen in runden Klammern vor den Ausdruck der umgewandelt werden soll.\n", "\n", "Achtung: Das Umwandeln mit Type-Casting kommt meist auch mit einer gewissen Ungenauigkeit. Nachkommastellen werden einfach abgeschnitten." ] }, { "cell_type": "markdown", "id": "7f4ea5c4", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Schema\n", "```\n", "() \n", "```\n", "\n", "Beispiele\n", "```java\n", "(int) 2.0\n", "(float) 3.1415\n", "(long) (5.6 * 2.1)\n", "```" ] }, { "cell_type": "markdown", "id": "577541b1", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Miniübung" ] }, { "cell_type": "markdown", "id": "664b88a1", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "- Übernehmen Sie die Berechnung aus der letzten Miniaufgabe.\n", "- Erweitern Sie Ihren Code so, dass die Stückangabe als Variable vom Typ `int` berechnet und dann ausgegeben wird." ] }, { "cell_type": "code", "execution_count": null, "id": "b4894160", "metadata": { "deletable": false, "scrolled": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class TypeCasts {\n", " public static void main(String[] args) {\n", " // Ihre Lösung kommt hier hin\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "605e404b", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "TypeCasts.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "098f6147", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ "### Genauigkeit von Zahlen" ] }, { "cell_type": "markdown", "id": "d773f507", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Die Genauigkeit von Zahlen im Computer ist Beschränkt. Nicht nur beim Type-Casting können so Fehler entstehen. Wir schauen uns nun drei Rechnungen an wo nur die Addition verwendet wird. Werden wir die erwarteten Resultate erhalten." ] }, { "cell_type": "markdown", "id": "8fbc8070", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Miniübung" ] }, { "cell_type": "markdown", "id": "f065d105", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "Addieren Sie dreimal die Zahl 0.1 zueinander und geben das Resultat auf die Konsole aus." ] }, { "cell_type": "code", "execution_count": null, "id": "198b82a3", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class Summation {\n", " public static void main(String[] args) {\n", " // Ihre Lösung kommt hier hin\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "eb477e34", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "Summation.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "3de8fdf0", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "Mathematisch gibt die folgende Formel für positive, ganze Zahlen immer 1:\n", "$$\\sum\\limits_{i=1}^{N}\\frac{1}{N}$$" ] }, { "cell_type": "code", "execution_count": null, "id": "e63310da", "metadata": { "deletable": false, "scrolled": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class Summation2{\n", " public static void main(String[] args) {\n", " double result = 1.0 / 6.0 + 1.0 / 6.0 + 1.0 / 6.0 +\n", " 1.0 / 6.0 + 1.0 / 6.0 + 1.0 / 6.0;\n", " System.out.println(\"Erwartet 1.0, tatsächlich \" + result);\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "ce10c44a", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "Summation2.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "939c9b06", "metadata": { "deletable": false, "slideshow": { "slide_type": "skip" } }, "source": [ "Dies zeigt, der Computer rechnet dies aus und löst die Aufgabe nicht irgendwie algebraisch.\n", "\n", "Nachfolgend sehen Sie ein Beispiel einer Aufgabe in einem Lernsetting. Es geht darum drei Zahlen zu Summieren." ] }, { "cell_type": "code", "execution_count": null, "id": "2ff39fca", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "public class Summation3 {\n", " public static void main(String[] args) {\n", " double a = 13.0;\n", " double b = Math.PI;\n", " double c = 21.45;\n", "\n", " double solution_student = a + b + c;\n", " System.out.println(\"The solution of the student is: \" + solution_student);\n", "\n", " double solution_teacher = a + c + b;\n", " System.out.println(\"The solution of the teacher is: \" + solution_teacher);\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "id": "d7615f0b", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "Summation3.main(new String[0]);" ] }, { "cell_type": "markdown", "id": "2a0bf03c", "metadata": { "deletable": false, "slideshow": { "slide_type": "fragment" } }, "source": [ "Diese Beispiele zeigen, dass man bei Gleitkommazahlen immer aufpassen muss mit der Genauigkeit.\n", "\n", "Dies wird später im Kurs vorallem auch beim Testen von Programmen erneut wichtig." ] }, { "cell_type": "markdown", "id": "e84b0f3a", "metadata": { "deletable": false, "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Diskussion" ] }, { "cell_type": "markdown", "id": "23050628", "metadata": { "deletable": false, "slideshow": { "slide_type": "-" } }, "source": [ "- Zahlen vom Typ `float` werden mit 32 Bits dargestellt. Mit 32 Bits lassen sich $2^{32}$ unterschiedliche Werte darstellen.\n", "- Der Wertebereich ist ungefähr $-3.4 \\cdot 10^{38}$ bis $3.4 \\cdot 10^{38}$, das ist ein Intervall der Grösse $2^{162}$.\n", "- Intuition: In der wissenschaftlichen Schreibweise von Zahlen (z.B.: $3.14159\\cdot10^{7}$), hat `float` eine Genauigkeit von 6 oder 7 signifikanten Dezimalstellen, für `double` sind es 14 bis 15 signifikante Dezimalstellen.\n", "- Der absolute Abstand zweier benachbarter, darstellbaren Zahlen rund um 0.0 ist kleiner als für Zahlen nahe der Grenzen des darstellbaren Wertebereichs.\n", "\n", "Interessierte finden eine ausführlichere und detailliertere Diskussion rund um die Darstellung und Genauigkeit von `float` [hier](https://introcs.cs.princeton.edu/java/91float/)." ] }, { "cell_type": "markdown", "id": "0a086a37", "metadata": { "deletable": false, "slideshow": { "slide_type": "slide" } }, "source": [ "### Take Home\n", "\n", "- Zwei Arten von Zahlen mit unterschiedlichen Zielen und Genauigkeit.\n", "- Hierarchie von Zahlen: `int`, `long`, `float`, `double`\n", "- Type Casting zum Umwandeln von Werten auf Kosten der Genauigkeit.\n", "- Rechnungen mit den kennen gelernten Typen sind nicht immer exakt." ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Java [conda env:ijava]", "language": "java", "name": "conda-env-ijava-java" }, "language_info": { "codemirror_mode": "java", "file_extension": ".jshell", "mimetype": "text/x-java-source", "name": "Java", "pygments_lexer": "java", "version": "17.0.3-internal+0-adhoc..src" } }, "nbformat": 4, "nbformat_minor": 5 }