4. Zahlen

In diesem Kapitel werden wir uns mit ganzen Zahlen und Fliesskommazahlen beschäftigen. Wir werden feststellen, das der Zahlenraum mit ganzen Zahlen in Python nahezu unendlich ist und das es bei Fliesskommazahlen immer mit Rundungsfehlern zu rechnen ist.

4.1. Ganze Zahlen

Eine grosse Besonderheit gegenüber anderen Programmiersprachen ist, dass die Grösse von ganzen Zahlen (int) nur durch den Speicherplatz limitiert ist. Sie müssen daher nie Angst haben, dass Sie den zulässigen Zahlenraum überschreiben.

x = 2 ** 1000
print(x)                     # Ausgabe: 12676506002282294014996703205376
type(x)                      # < class 'int' >

Allerdings rechnet Python deutlich schneller, solange sich die Zahlen eines Ausdrucks im 64-bit-Zahlenraum liegen. Python kann dann die Rechenfunktionen der CPU unmittelbar bennutzen.

Die grösste positive Zahl dieses Zahlenraums können Sie mit sys.maxsize ermitteln.

Python kennt keine vorzeichenlose Zahlen (also uint oder unsigned int wie in manchen anderen Sprachen)

4.1.1. Division

Eine weitere Python Besonderheit ist, das eine gewöhnliche Division immer eine Fliesskommazahl als Ergebnis liefert.

print( 2/3, 6/3 )             # Ausgabe: 0.6666666666666666 2.0

Wenn man explizit eine ganzzahlige Division wünscht, so müssen Sie den Operator // verwenden.

print( 2//3, 6//3 )           # Ausgabe: 0 2

Eine Division durch 0 löst wie in jeder anderen Programmiersprache in Python erwartungsgemäss einen Fehler aus, egal ob man mit / oder // arbeitet.

a = 7; b = 0
a / b                          # ZeroDivisionError: division by zero
a // b                         # ZeroDivisionError: integer division or module by zero

4.1.2. Binäre und hexadezimale Darstellung

Zahlen, die mit 0x beginnen, werden durch Python als hexadezimale Zahlen interpretiert. Umgekehrt können Sie eine vorhandene Zahl mit der Funktion hex in einer Zeichenkette in hexadezimaler Darstellung umwandeln.

print(0x40)                 # 160

x = 165
print(hex(x))               # 0xa5

Analog zu hexadezimal werden Zahlen die mit 0b beginnen als binär interpretiert und mit der Funktion bin berechnet. Für oktale Zahlen wird das Präfix 0o bzw. die Funktion oct benutzt.

print(0b10001)              # 17

x = 165
print(bin(x))               # 0b10100101
print(oct(x))               # 0o245

4.1.3. Zufallszahlen

Ganzzahlige Zufallszahlen erzeugen Sie am einfachsten mit der Funktion randint aus dem random Modul. randint(min, max) liefert ganze Zahlen, die die Grenzwert min und max einschliessen. Früher oder später werden die Zahlen 0 und 7 als Ergebnis zurückgeliefert.

rom random import randint
print(randint(0, 7)          # Zufallszahl zwischen 0 (inklusive) und 7 (inklusive)

4.2. Fliesskommazahlen

Fliesskommazahlen (Datentyp float) wrden in Python im 64 bit Format dargestellt. Die grösste darstellbare Zahl ist damit ca. 20 x 10308, die Anzahl der Kommastellen beträgt 16.

Gängige mathematische Funktionen befidnen sich im math-Modul. Man muss es vorab importieren, bevor man mit quadrathwurzel, Sinus, Cosinus oder mit anderen Funktionen Berechnungen durchführen kann. Die Funktion Pi (Kreisrundungszahl) ist ebenfalls in dem Modul math in Form von math.pi verfügbar.

import math
print(math.sqrt(2))         # Ausgabe: 1.4142135623730951
print(math.sin(0.4))        # Ausgabe: 0.3894183423086505

4.2.1. Rundungsfehler

Bei Berechnungen mit Fliesskommazahlen kommt es zu Rundungsfehlern.
Das ist aber kein Problem der Programmiersprache Python, sondern es hat mit der binären Darstellung von Zahlen zu tun und ist leider unvormeidbar.
die folgende Berechnung mit den Variablen a bis d gibt dafür ein Beispiel. Eigentlich müssen c und d in diesem Beispiel jeweils den Wert 0.8 enthalten. Aufgrund von Rundungsfehlern ist das aber nicht der Fall.

a = 0.7
b = 0.9
c = a + 0.1
d = b - 0.1
print( c == d )            # Ausgabe: False
print( c - d )             # Ausgabe: 1.11022302462251565e-16

4.2.2. Zufallszahlen

Wie schon in Kapitel Zufallszahlen vorgestellte random-Modul enthält auch mehrere Funktionen zur Erzeugung von pseudozufälligen Fliesskommazahlen. Random liefert Zahlen zwischen 0 (inklusiv) und 1 (exklusiv). uniform(min, max) produziert Zahlen zwischen min und max. Der untere Grenzwert kann auf jedenfall ein Ergebnis der Funktion sein. Beim oberen Grenzwert hängt der Wert aber vom Rundungsfehler ab.

from random import random, uniform
print(random())             # zwischen 0 und 1
                            # Ausgabe Beipiel: 0.9399897956383795
print(uniform(2.0, 7.5))    # zwischen 2.0 und 7.5
                            # Ausgabe Beispiel: 3.287799000324788

Mehr Funktionen zur Berechnung von Zufallszahlen

Das random Modul kann sehr viel mehr als die hier angegebenen Funktionen.
Viel mehr Funktionen findet man in der vollständigen Referenz von Python
https://docs.python.org/3/library/random.html

4.3. Komplexe Zahlen, Brüche und Festkommazahlen

Eine Stärke von Python gegenüber vielen anderen Programmiersprachen ist, dass Sie auch auf e§twas exotischere Wünsche von Mathematikern und Naturwissenschaftlern Rücksicht nimmt. So zählen komplexe Zahlen zu den elementaren Datentypen von Python. Erweiterungsmodule ermöglichen es auch mit Brüchen sowie mit Dezimalzahlen zu rechnen.

4.3.1. Komplexe Zahlen

Komplexe Zahlen bestehen aus Real- und Imaginärteilen und erweitern den Zahlenraum dahingehend, dass beispielsweise auch die Quadratwurzel einer negativen Zahl abgebildet werden kann.

In Python wird der Imaginärteil einer Zahl durch den Buchstaben j oder J dargestellt.
Aus einer gegebenen komplexen Zahl können diese Bestandteilte den Eigenschaften real und imag entnommen werden.

x = 2 + 3j
y = 1 - 4j
z = x * y
print(z)                 # Ausgabe: 14 - 5j
print(type(z))           # Ausgabe: <class 'complex'>
print(z.real, z.imag)    # Ausgabe: 14.0 -5.0

Komplexe Zahlen können auch mit dem Schlüsselwort complex aus zwei Fliesskommazahlen gebildet werden. die den real als auch imaginär Teil angeben.

complex(0.5, -0.7)        # Ausgabe: (0.5-0.7j)

Auch wenn das o.a. Beispiel auf Anhieb funktioniert hat, kommen die Funktionen aus dem math-Modul nicht mit komplexen Zahlen zurecht. Stattdessen müssen Sie auf Funktionen aus dem cmath-Modul zurückgeben.

import cmath
cmath.sqrt(-1)           # 1j
cmath.phase(1j)          # 1.5707963267948966
                         # Pi/2, also 90 Grad

4.3.2. Rationale Zahlen

Das Modul fractions stellt Funktionen für das Arbeiten mit fraktionalen Zahlen oder Brüchen zur Verfügung. Dieses Modul muss am Anfang des Scripts importiert werden.

from fractions import Fraction

x = Fraction('1/3')
y = Fraction('1/2')
x + y
Fraction(5, 6)            # 1/3 + 1/2 ergibt 5/6

4.3.3. Boolesche Werte

Um genau zu sein, sind boolesche Werte eigentlich keine Zahlen. Vielmehr können Sie nur die Zustände True oder False speichern bzw, verarbeiten. Genau die ist aber bei der Auswertung von Bedingen aber häufig erforderlich und rechtfertigt den eigenen Datentyp bool.

a = True
b = 7 == 8
print(b)                  # Ausgabe: False
print(type(b))            # Ausgabe: <class 'bool'>
print(not b)              # Ausgabe: True

Boolesche Werte können mit Zahlen dargestellt werden.
True erhält dadurch den Wert 1, False den Wert 0

print(int(True), int(False))            # Ausgabe: 1 0

Wenn Zahlen als Boolesche Werte dargestellt werden soll, dann gilt die Zahl 0 als False, alle anderen Werte True

x = 7
if x:
  print("x hat einen Wert ungleich 0.")

4.4. Aufgaben:

1.) Wie führt man eine ganzzahlige Division durch?

2.) Sie wollen den Oktalcode 750 in binärer Darstellung anzeigen. Wie gehen sie hier vor?

3.) Wie erzeugen Sie Zufallszahlen zwischen 1 und 49?

4.) Sie benötigen zwei Zufallszahlen zwischen 0.0 und 10.0. Schreiben Sie dazu einen geeigneten Code.

5.) Sie wollen Geldbeträge ohne Rundungsfehler verarbeiten. Welchen Datentyp verwenden Sie?

6.) Welchem Datentyp ist True zugeordnet.