Datentypen: Difference between revisions
No edit summary |
No edit summary |
||
| Line 101: | Line 101: | ||
==bool== | ==bool== | ||
--- | ---- | ||
Bool ist eine eigene Klasse. Es enthält die Eigenschaften `True` und `False`. | Bool ist eine eigene Klasse. Es enthält die Eigenschaften `True` und `False`. | ||
| Line 139: | Line 138: | ||
==Bytes== | ==Bytes== | ||
--- | ---- | ||
Bytes sind Werte die mit 8-Bit dargestellt werden können (0 ... 255). Bytes kommen als Datentyp in Python nicht vor. Es können aber Zahlen und Strings in eine Bytefolge und umgekehrt umgewandelt werden. Das wird benutzt um Daten zur Übertragung zu serialisieren. Dazu gibt es 2 Datentypen: | Bytes sind Werte die mit 8-Bit dargestellt werden können (0 ... 255). Bytes kommen als Datentyp in Python nicht vor. Es können aber Zahlen und Strings in eine Bytefolge und umgekehrt umgewandelt werden. Das wird benutzt um Daten zur Übertragung zu serialisieren. Dazu gibt es 2 Datentypen: | ||
| Line 149: | Line 147: | ||
==Literale== | ==Literale== | ||
--- | ---- | ||
Wenn man etwas über Python oder auch andere Programmiersprachen ließt, trifft man immer wieder auf den Begriff **Literal**. Was ist damit gemeint? | Wenn man etwas über Python oder auch andere Programmiersprachen ließt, trifft man immer wieder auf den Begriff **Literal**. Was ist damit gemeint? | ||
| Line 157: | Line 154: | ||
==int== | ==int== | ||
--- | ---- | ||
`int` ist die Klasse für ganze Zahlen. Sie enthält alle positiven und negativen ganzen Zahlen. Die Größe eines `int` ist nicht festgelegt. Sie ist praktisch durch die Speichergröße begrenzt. | `int` ist die Klasse für ganze Zahlen. Sie enthält alle positiven und negativen ganzen Zahlen. Die Größe eines `int` ist nicht festgelegt. Sie ist praktisch durch die Speichergröße begrenzt. | ||
| Line 179: | Line 175: | ||
===Methoden von `int`=== | ===Methoden von `int`=== | ||
>>> dir(int) | |||
>>> dir(int) | ['__class__', '__name__', 'from_bytes', 'to_bytes', '__bases__', '__dict__'] | ||
['__class__', '__name__', 'from_bytes', 'to_bytes', '__bases__', '__dict__'] | |||
### from_bytes(bytearray, ‘little|big’) | ### from_bytes(bytearray, ‘little|big’) | ||
| Line 202: | Line 196: | ||
Bei sehr großen Zahlen unterteilen wir die tausender Stellen gerne mit Punkten. Das ist bei der Eingabe von Zahlen auch in Python möglich. Allerdings wird hier nicht der Punkt, sondern der Unterstrich ‘_’ verwendet: | Bei sehr großen Zahlen unterteilen wir die tausender Stellen gerne mit Punkten. Das ist bei der Eingabe von Zahlen auch in Python möglich. Allerdings wird hier nicht der Punkt, sondern der Unterstrich ‘_’ verwendet: | ||
>>> a = 100_000_000 | |||
>>> a = 100_000_000 | >>> a | ||
>>> a | 100000000 | ||
100000000 | >>> | ||
>>> | |||
===Funktionen die auf `int` angewendet werden können.=== | ===Funktionen die auf `int` angewendet werden können.=== | ||
| Line 251: | Line 243: | ||
Die minimale bzw. maximale Größe von `float` in CPython beträgt: | Die minimale bzw. maximale Größe von `float` in CPython beträgt: | ||
Python 3.10.4 (/usr/bin/python3) | |||
Python 3.10.4 (/usr/bin/python3) | >>> import sys | ||
>>> import sys | >>> print(sys.float_info) | ||
>>> print(sys.float_info) | sys.float_info( | ||
sys.float_info( | max=1.7976931348623157e+308, | ||
max_exp=1024, | |||
max_10_exp=308, | |||
min=2.2250738585072014e-308, | |||
min_exp=-1021, | |||
min_10_exp=-307, | |||
dig=15, | |||
mant_dig=53, | |||
epsilon=2.220446049250313e-16, | |||
radix=2, | |||
rounds=1) | |||
>>> | |||
>>> | |||
Quelle: Steinkamp, Veit, Der Python-Kurs für Ingenieure und Naturwissenschaftler, 1.Auflage, Rheinwerk Verlag, Bonn 2021, S.31 | Quelle: Steinkamp, Veit, Der Python-Kurs für Ingenieure und Naturwissenschaftler, 1.Auflage, Rheinwerk Verlag, Bonn 2021, S.31 | ||
| Line 279: | Line 269: | ||
Durch die begrenzte Größe kommt es zu Rundungsfehlern. | Durch die begrenzte Größe kommt es zu Rundungsfehlern. | ||
>>> 10.99999 | |||
>>> 10.99999 | 10.99999 | ||
10.99999 | >>> 10.999999 | ||
>>> 10.999999 | 11.0 | ||
11.0 | |||
> Wenn insgesamt mehr als 7 Stellen vorhanden sind wird die Fließkommazahl gerundet! | > Wenn insgesamt mehr als 7 Stellen vorhanden sind wird die Fließkommazahl gerundet! | ||
| Line 291: | Line 279: | ||
Der Übergang zum Aufrunden liegt aber bei 0.0000006: | Der Übergang zum Aufrunden liegt aber bei 0.0000006: | ||
>>> 9.99999959 | |||
>>> 9.99999959 | 9.999999 | ||
9.999999 | >>> 9.9999996 | ||
>>> 9.9999996 | 10.0 | ||
10.0 | >>> | ||
>>> | |||
# Noch präzieser: | |||
# Noch präzieser: | >>> 9.99999959999 | ||
>>> 9.99999959999 | 9.999999 | ||
9.999999 | >>> 9.999999599991 | ||
>>> 9.999999599991 | 10.0 | ||
10.0 | >>> | ||
>>> | |||
Intern wird wohl mit einer 12-stelligen Mantisse gerechnet. | Intern wird wohl mit einer 12-stelligen Mantisse gerechnet. | ||
| Line 323: | Line 309: | ||
Gibt eine ganze Zahl zurück, wobei x auf positive Unendlichkeit gerundet wird. | Gibt eine ganze Zahl zurück, wobei x auf positive Unendlichkeit gerundet wird. | ||
>>> math.ceil(3.14) | |||
>>> math.ceil(3.14) | 4 | ||
4 | >>> | ||
>>> | |||
`**math.copysign(*x*, *y*)**` | `**math.copysign(*x*, *y*)**` | ||
| Line 333: | Line 317: | ||
Gibt x mit dem Vorzeichen von y zurück. | Gibt x mit dem Vorzeichen von y zurück. | ||
>>> math.copysign(math.pi, -1) | |||
>>> math.copysign(math.pi, -1) | -3.141593 | ||
-3.141593 | >>> | ||
>>> | |||
`**math.fabs(*x*)**` | `**math.fabs(*x*)**` | ||
| Line 343: | Line 325: | ||
Gibt den absoluten Wert von x zurück. | Gibt den absoluten Wert von x zurück. | ||
>>> math.copysign(math.pi, -1) | |||
>>> math.copysign(math.pi, -1) | -3.141593 | ||
-3.141593 | |||
>>> math.fabs(_) | |||
>>> math.fabs(_) | 3.141593 | ||
3.141593 | >>> | ||
>>> | |||
`**math.floor(*x*)**` | `**math.floor(*x*)**` | ||
| Line 356: | Line 336: | ||
Gibt eine ganze Zahl zurück, wobei x gegen negative Unendlichkeit gerundet wird. | Gibt eine ganze Zahl zurück, wobei x gegen negative Unendlichkeit gerundet wird. | ||
>>> math.floor(3.14) | |||
>>> math.floor(3.14) | 3 | ||
3 | >>> math.floor(-3.14) | ||
>>> math.floor(-3.14) | -4 | ||
-4 | >>> | ||
>>> | |||
`**math.fmod(*x*, *y*)**` | `**math.fmod(*x*, *y*)**` | ||
| Line 368: | Line 346: | ||
Gibt den Rest von x/y zurück. | Gibt den Rest von x/y zurück. | ||
>>> math.fmod(10, 3) | |||
>>> math.fmod(10, 3) | 1.0 | ||
1.0 | >>> | ||
>>> | |||
`**math.isfinite(*x*)**` | `**math.isfinite(*x*)**` | ||
| Line 380: | Line 356: | ||
Endlich ist eine Zahl dann, wenn sie im gültigen Zahlenbereich von `float` liegt. | Endlich ist eine Zahl dann, wenn sie im gültigen Zahlenbereich von `float` liegt. | ||
>>> math.isfinite(1e40) | |||
>>> math.isfinite(1e40) | False | ||
False | >>> math.isfinite(1e38) | ||
>>> math.isfinite(1e38) | True | ||
True | >>> | ||
>>> | |||
`**math.isinf(*x*)**` | `**math.isinf(*x*)**` | ||
| Line 394: | Line 368: | ||
Unendlich ist eine Zahl dann, wenn sie ausserhalb des gültigen Zahlenbereichs von `float` liegt. | Unendlich ist eine Zahl dann, wenn sie ausserhalb des gültigen Zahlenbereichs von `float` liegt. | ||
>>> math.isinf(1e40) | |||
>>> math.isinf(1e40) | True | ||
True | >>> math.isinf(1e38) | ||
>>> math.isinf(1e38) | False | ||
False | >>> | ||
>>> | |||
`**math.modf(*x*)**` | `**math.modf(*x*)**` | ||
| Line 406: | Line 378: | ||
Gibt ein Tupel aus zwei Floats zurück, die den gebrochenen und den ganzzahligen Teil von x darstellen. Beide Rückgabewerte haben das gleiche Vorzeichen wie x. | Gibt ein Tupel aus zwei Floats zurück, die den gebrochenen und den ganzzahligen Teil von x darstellen. Beide Rückgabewerte haben das gleiche Vorzeichen wie x. | ||
>>> math.modf(3.14) | |||
>>> math.modf(3.14) | (0.1400001, 3.0) | ||
(0.1400001, 3.0) | >>> | ||
>>> | |||
Hier sieht man einen der gefürchten Rundungsfehler bei floats. | Hier sieht man einen der gefürchten Rundungsfehler bei floats. | ||
| Line 418: | Line 388: | ||
Gibt x als Potenz von y zurück. | Gibt x als Potenz von y zurück. | ||
>>> math.pow(2, 8) | |||
>>> math.pow(2, 8) | 256.0 | ||
256.0 | >>> | ||
>>> | |||
`**math.sqrt(*x*)**` | `**math.sqrt(*x*)**` | ||
| Line 428: | Line 396: | ||
Gibt die Quadratwurzel von x zurück. | Gibt die Quadratwurzel von x zurück. | ||
>>> math.sqrt(2) | |||
>>> math.sqrt(2) | 1.414214 | ||
1.414214 | >>> | ||
>>> | |||
`**math.trunc(*x*)**` | `**math.trunc(*x*)**` | ||
| Line 438: | Line 404: | ||
ergibt eine ganze Zahl, wobei x gegen 0 gerundet wird. | ergibt eine ganze Zahl, wobei x gegen 0 gerundet wird. | ||
>>> math.trunc(3.14) | |||
>>> math.trunc(3.14) | 3 | ||
3 | >>> math.trunc(-3.14) | ||
>>> math.trunc(-3.14) | -3 | ||
-3 | >>> | ||
>>> | |||
**Ausserdem die Konstanten:** | **Ausserdem die Konstanten:** | ||
| Line 456: | Line 420: | ||
Die Kreiszahl PI, mit begrenzter Genauigkeit. | Die Kreiszahl PI, mit begrenzter Genauigkeit. | ||
>>> math.pi | |||
>>> math.pi | 3.141593 | ||
3.141593 | >>> | ||
>>> | |||
### Rechnen mit float führt manchmal zu erstaunlichen Ergebnissen. | ### Rechnen mit float führt manchmal zu erstaunlichen Ergebnissen. | ||
| Line 466: | Line 428: | ||
Da `float` nur eine begrenzte Auflösung bietet, kommt es gelegentlich zu Rundungsfehlern. | Da `float` nur eine begrenzte Auflösung bietet, kommt es gelegentlich zu Rundungsfehlern. | ||
>>> 10.99999 | |||
>>> 10.99999 | 10.99999 | ||
10.99999 | >>> 10.999999 | ||
>>> 10.999999 | 11.0 | ||
11.0 | |||
> Wenn insgesamt mehr als 7 Stellen vorhanden sind wird die Fließkommazahl gerundet! | > Wenn insgesamt mehr als 7 Stellen vorhanden sind wird die Fließkommazahl gerundet! | ||
| Line 478: | Line 438: | ||
Der Übergang zum Aufrunden liegt aber bei 0.0000006: | Der Übergang zum Aufrunden liegt aber bei 0.0000006: | ||
>>> 9.99999959 # 9 Stellen | |||
>>> 9.99999959 # 9 Stellen | 9.999999 | ||
9.999999 | >>> 9.9999996 # 8 Stellen | ||
>>> 9.9999996 # 8 Stellen | 10.0 | ||
10.0 | >>> | ||
>>> | |||
# Noch präzieser: | |||
# Noch präzieser: | >>> 9.99999959999 # 12 Stellen | ||
>>> 9.99999959999 # 12 Stellen | 9.999999 | ||
9.999999 | >>> 9.999999599991 # 13 Stellen | ||
>>> 9.999999599991 # 13 Stellen | 10.0 | ||
10.0 | >>> | ||
>>> | |||
So wie es aussieht wird intern mit 12 Stellen gerechnet und dann auf 7 Stellen gerundet. | So wie es aussieht wird intern mit 12 Stellen gerechnet und dann auf 7 Stellen gerundet. | ||
| Line 505: | Line 463: | ||
Man kann auch eine entsprechende Funktion schreiben. Hier ein Beispiel in C: | Man kann auch eine entsprechende Funktion schreiben. Hier ein Beispiel in C: | ||
bool almostEqual (float a, float b) | |||
bool almostEqual (float a, float b) | { | ||
{ | return fabs(a - b) <= FLT_EPSILON; | ||
} | |||
} | |||
===nan=== | ===nan=== | ||
| Line 516: | Line 472: | ||
Nan steht für Not a Number, also keine Zahl und existiert nur für floats. Es Bedeutet, das hier kein Wert zur Verfügung steht. | Nan steht für Not a Number, also keine Zahl und existiert nur für floats. Es Bedeutet, das hier kein Wert zur Verfügung steht. | ||
>>> n = float('nan') | |||
>>> n = float('nan') | >>> n | ||
>>> n | nan | ||
nan | >>> n = float('Nan') | ||
>>> n = float('Nan') | >>> n | ||
>>> n | nan | ||
nan | >>> n = float('NaN') | ||
>>> n = float('NaN') | >>> n | ||
>>> n | nan | ||
nan | >>> n = float('NAN') | ||
>>> n = float('NAN') | >>> n | ||
>>> n | nan | ||
nan | >>> | ||
>>> | |||
Mit der folgenden Funktion aus dem Modul math kann darauf getestet werden: | Mit der folgenden Funktion aus dem Modul math kann darauf getestet werden: | ||
| Line 538: | Line 492: | ||
Gibt True zurück, wenn x nicht eine Zahl ist | Gibt True zurück, wenn x nicht eine Zahl ist | ||
>>> a = 42 | |||
>>> a = 42 | >>> n = float('nan') | ||
>>> n = float('nan') | >>> math.isnan(a) | ||
>>> math.isnan(a) | False | ||
False | >>> math.isnan(n) | ||
>>> math.isnan(n) | True | ||
True | >>> | ||
>>> | |||
> ‘==’ funktioniert nicht bei nan! | > ‘==’ funktioniert nicht bei nan! | ||
> | > | ||
>>> n = float('nan') | |||
>>> n = float('nan') | >>> m = float('nan') | ||
>>> m = float('nan') | >>> n == m | ||
>>> n == m | False | ||
False | >>> n is m | ||
>>> n is m | False | ||
False | >>> id(n) | ||
>>> id(n) | 1073493184 | ||
1073493184 | >>> id(m) | ||
>>> id(m) | 1073493216 | ||
1073493216 | >>> | ||
>>> | |||
Nan wird verwendet wenn ... | Nan wird verwendet wenn ... | ||
| Line 569: | Line 519: | ||
==str== | ==str== | ||
--- | ---- | ||
[[Kategorie:MPKurs2022]] | [[Kategorie:MPKurs2022]] | ||
Revision as of 20:42, 1 August 2022
Übersicht
Python kennt die folgenden Datentypen:
- int - ganze Zahlen
- float - gebrochene Zahlen
- complex - komplexe Zahlen
- str - Zeichenketten
- bool - Wahrheitswerte
- none - nichts
Datentypen sind in Python als Klassen implementiert.
>>> type(42)
<class 'int'>
>>> type(3.14)
<class 'float'>
>>> type('Hallo')
<class 'str'>
>>>
Deshalb haben sie auch Methoden:
>>> dir(int) ['__class__', '__name__', 'from_bytes', 'to_bytes', '__bases__', '__dict__'] >>> dir(str) ['__class__', '__name__', 'count', 'endswith', 'find', 'format', 'index', 'isalpha', 'isdigit', 'islower', 'isspace', 'isupper', 'join', 'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rsplit', 'rstrip', 'split', 'startswith', 'strip', 'upper', '__bases__', '__dict__', 'center', 'encode', 'partition', 'rpartition', 'splitlines']
>>> dir(float)
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400e8bc6 PS : 0x00060630 A0 : 0x800df1a5 A1 : 0x3ffc25d0
A2 : 0x3f409668 A3 : 0x00000002 A4 : 0x3ffc26b0 A5 : 0x00000000
A6 : 0x000000b3 A7 : 0x3ffc2810 A8 : 0x00000000 A9 : 0x3ffc25d0
A10 : 0x00000000 A11 : 0x3ffc2a58 A12 : 0x00000000 A13 : 0x00000000
A14 : 0x00000001 A15 : 0x3f409668 SAR : 0x0000001e EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000004 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
ELF file SHA256: 0000000000000000
Backtrace: 0x400e8bc3:0x3ffc25d0 0x400df1a2:0x3ffc2610 0x400df214:0x3ffc2630 0x400eaa5d:0x3ffc26b0 0x400e34be:0x3ffc26e0 0x400df489:0x3ffc2710 0x400eced9:0x3ffc2730 0x400e3578:0x3ffc27d0 0x400df489:0x3ffc2830 0x400df4b2:0x3ffc2850 0x40117cc8:0x3ffc2870 0x40117dbd:0x3ffc2900 0x400f4a6c:0x3ffc2930 0x40095701:0x3ffc2960
Rebooting...
_ __ _
_ _(_)/ _| | _____ __
| | | | | |_| |/ _ \ \ /\ / /
| |_| | | _| | (_) \ V V /
\__,_|_|_| |_|\___/ \_/\_/
APIKEY: FFBFFD22
```
None
Auch None ist eine eigene Klasse:
>>> type(None) <class 'NoneType'> >>>
>>> dir(None) ['__class__'] >>>
Diese Klasse hat aber keine Methoden.
Tip pythonisch:
Wenn man auf None testen will sollte das mit ‘is’, dem Identitätsvergleich, geschen und nicht mit ‘==’ dem Wertevergleich.
Eine Funktion ohne Rückgabewert liefert None zurück:
>>> def test_none():
pass
>>> a = test_none()
>>> a
>>> # a liefert keinen Wert zurück
# Es geht aber auch einfach, wie fast alles in Python:
>>> a = None
>>> a
>>>
>>> a is None
True # Der Inhalt von a ist None!
>>>
>>> a == None # Geht auch, ist aber nicht pythonisch!
True
>>>
bool
Bool ist eine eigene Klasse. Es enthält die Eigenschaften `True` und `False`.
Der Versuch Methoden von `bool` zu finden endet im Nirwana bei der Guru Meditation:
>>> type(True) <class 'bool'> >>>
>>> dir(bool)
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400e8bc6 PS : 0x00060730 A0 : 0x800df1a5 A1 : 0x3ffc25d0
A2 : 0x3f40873c A3 : 0x00000002 A4 : 0x3ffc26b0 A5 : 0x00000000
A6 : 0x000000b3 A7 : 0x3ffc2810 A8 : 0x00000000 A9 : 0x3ffc25d0
A10 : 0x00000000 A11 : 0x3ffc2a58 A12 : 0x00000000 A13 : 0x00000000
A14 : 0x00000001 A15 : 0x3f40873c SAR : 0x00000020 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000004 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
ELF file SHA256: 0000000000000000
Backtrace: 0x400e8bc3:0x3ffc25d0 0x400df1a2:0x3ffc2610 0x400df214:0x3ffc2630 0x400eaa5d:0x3ffc26b0 0x400e34be:0x3ffc26e0 0x400df489:0x3ffc2710 0x400eced9:0x3ffc2730 0x400e3578:0x3ffc27d0 0x400df489:0x3ffc2830 0x400df4b2:0x3ffc2850 0x40117cc8:0x3ffc2870 0x40117dbd:0x3ffc2900 0x400f4a6c:0x3ffc2930 0x40095701:0x3ffc2960
Rebooting...
_ __ _
_ _(_)/ _| | _____ __
| | | | | |_| |/ _ \ \ /\ / /
| |_| | | _| | (_) \ V V /
\__,_|_|_| |_|\___/ \_/\_/
APIKEY: FFBFFD22
`bool` hat wohl keine Methoden.
Bytes
Bytes sind Werte die mit 8-Bit dargestellt werden können (0 ... 255). Bytes kommen als Datentyp in Python nicht vor. Es können aber Zahlen und Strings in eine Bytefolge und umgekehrt umgewandelt werden. Das wird benutzt um Daten zur Übertragung zu serialisieren. Dazu gibt es 2 Datentypen:
- bytestring
- bytearray
Literale
Wenn man etwas über Python oder auch andere Programmiersprachen ließt, trifft man immer wieder auf den Begriff **Literal**. Was ist damit gemeint?
Als Literal bezeichnet man die schriftliche Darstellung einer Zahl. Also z.B. 1, 1.0 oder 1e0. Das sind drei unterschiedliche Literale der Zahl 1.
int
`int` ist die Klasse für ganze Zahlen. Sie enthält alle positiven und negativen ganzen Zahlen. Die Größe eines `int` ist nicht festgelegt. Sie ist praktisch durch die Speichergröße begrenzt.
>>> type(42) <class 'int'> >>> type(-42) <class 'int'> >>> type(0) <class 'int'> >>>
>>> 10 ** 100 1000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000 >>> 10 ** 1000000 MemoryError: memory allocation failed, allocating 34258 bytes >>>
Methoden von `int`
>>> dir(int) ['__class__', '__name__', 'from_bytes', 'to_bytes', '__bases__', '__dict__']
- from_bytes(bytearray, ‘little|big’)
Wandelt Bytes in ein `int` um. Es muss die Reihenfolge der Bytes angegeben werden, `little` Endian oder `big` Endian.
[1](https://www.codegrepper.com/code-examples/python/from_bytes+python)
[2](https://www.delftstack.com/de/howto/python/how-to-convert-bytes-to-integers/)
[3](https://stackoverflow.com/questions/50509017/how-is-int-from-bytes-calculated)
- to_bytes(int, ‘little|big’)
Wandelt ein `int` in Bytes um. Es muss die Reihenfolge der Bytes angegeben werden, `little` Endian oder `big` Endian.
- Unterstriche zur Strukturierung großer Zahlen
Bei sehr großen Zahlen unterteilen wir die tausender Stellen gerne mit Punkten. Das ist bei der Eingabe von Zahlen auch in Python möglich. Allerdings wird hier nicht der Punkt, sondern der Unterstrich ‘_’ verwendet:
>>> a = 100_000_000 >>> a 100000000 >>>
Funktionen die auf `int` angewendet werden können.
abs(),
float
[4](https://medium.com/@tuenguyends/pythons-real-number-float-type-ed502b22b496)
Gleitkommazahlen werden grundsätzlich nur als Dezimalzahlen dargestellt. Die Trennung zwischen dem ganzzahligen und dem gebrochenen Teil erfolgt in Deutschland durch ein Komma. International wird dazu der Punkt verwendet. Dementsprechend verwenden auch Programmiersprachen üblicherweise den **Punkt**, denn sie sind international.
- Die Trennung von ganzzahligen und gebrochen Teil einer Zahl erfolgt durch den Punkt.**
Eine Gleitkommazahl kann als Dezimalbruch oder in Expotentialschreibweise dargestellt werden.
- Dezimalbruch
Beispiel: 123.456
- Exponential (wissenschaftlich)
Hier erfolgt die Darstellung als Mantisse und Exponent:
Zahl = Mantisse * Exponent (Basis10)
Die **Mantisse** ist eine Gleitkommazahl mit üblicherweise nur einer Vorkommastelle
Der **Exponent** ist immer ein Vielfaches von 10. Er muss **immer ganzzahlig** sein!
Zur Kennzeichnung dieser Schreibweise dient das e oder E.
Beispiele: 1.0e3 ⇒ 1000.0
3.14E7 ⇒ 3140000.0
7.35E-3 ⇒ 0.00735
Die maximale Größe von Mantisse und Exponent sind begrenzt:
Python werden Gleitkommazahlen in 64-bit gespeichert.
Die minimale bzw. maximale Größe von `float` in CPython beträgt:
Python 3.10.4 (/usr/bin/python3)
>>> import sys
>>> print(sys.float_info)
sys.float_info(
max=1.7976931348623157e+308,
max_exp=1024,
max_10_exp=308,
min=2.2250738585072014e-308,
min_exp=-1021,
min_10_exp=-307,
dig=15,
mant_dig=53,
epsilon=2.220446049250313e-16,
radix=2,
rounds=1)
>>>
Quelle: Steinkamp, Veit, Der Python-Kurs für Ingenieure und Naturwissenschaftler, 1.Auflage, Rheinwerk Verlag, Bonn 2021, S.31
Bei **Micropython** sieht es anders aus. Hier spielt der Platzbedarf eine große Rolle. Deshalb ist die Größe von Gleitkommazahlen hier eingeschränkt. `sys.float_info` gibt es im M5Stack-MP leider nicht. Eine konkrete Angabe zur maximalen Größe habe ich im Internet leider auch nicht finden können. Deshalb habe ich es ausprobiert:
- **Mantisse**: 9.999999 - also auf 6 Nachkommastellen bzw. auf insgesamt 7 Stellen. - **Exponent**: E-40 ... E38
Durch die begrenzte Größe kommt es zu Rundungsfehlern.
>>> 10.99999 10.99999 >>> 10.999999 11.0
> Wenn insgesamt mehr als 7 Stellen vorhanden sind wird die Fließkommazahl gerundet! >
Der Übergang zum Aufrunden liegt aber bei 0.0000006:
>>> 9.99999959 9.999999 >>> 9.9999996 10.0 >>> # Noch präzieser: >>> 9.99999959999 9.999999 >>> 9.999999599991 10.0 >>>
Intern wird wohl mit einer 12-stelligen Mantisse gerechnet.
> Beim Rechnen mit Fließkommazahlen kommt es gelegentlich zu Rundungsfehlern, weil gebrochene Zahlen intern nicht exakt dargestellt werden können. >
Die Wesentliche Eigenschaften von `float` wurden schon bei der Vorstellung von Python erörtert.
Die Funktionen für `int` lassen auch auf `float` anwenden. Im Modul math gibt es eine Reihe weitere Funktionen, die vor allem für den Typ `float` interssant sind.
Eine Übersicht findet man hier: [5](https://docs.micropython.org/en/v1.12/library/math.html)
Neben den trigonometrischen und logarithmischen Funktionen gibt es ein paar weitere die ich hier vorstellen möchte:
`**math.ceil(*x*)**`
Gibt eine ganze Zahl zurück, wobei x auf positive Unendlichkeit gerundet wird.
>>> math.ceil(3.14) 4 >>>
`**math.copysign(*x*, *y*)**`
Gibt x mit dem Vorzeichen von y zurück.
>>> math.copysign(math.pi, -1) -3.141593 >>>
`**math.fabs(*x*)**`
Gibt den absoluten Wert von x zurück.
>>> math.copysign(math.pi, -1) -3.141593 >>> math.fabs(_) 3.141593 >>>
`**math.floor(*x*)**`
Gibt eine ganze Zahl zurück, wobei x gegen negative Unendlichkeit gerundet wird.
>>> math.floor(3.14) 3 >>> math.floor(-3.14) -4 >>>
`**math.fmod(*x*, *y*)**`
Gibt den Rest von x/y zurück.
>>> math.fmod(10, 3) 1.0 >>>
`**math.isfinite(*x*)**`
Gibt `True` zurück, wenn x endlich ist.
Endlich ist eine Zahl dann, wenn sie im gültigen Zahlenbereich von `float` liegt.
>>> math.isfinite(1e40) False >>> math.isfinite(1e38) True >>>
`**math.isinf(*x*)**`
Gibt True zurück, wenn x unendlich ist.
Unendlich ist eine Zahl dann, wenn sie ausserhalb des gültigen Zahlenbereichs von `float` liegt.
>>> math.isinf(1e40) True >>> math.isinf(1e38) False >>>
`**math.modf(*x*)**`
Gibt ein Tupel aus zwei Floats zurück, die den gebrochenen und den ganzzahligen Teil von x darstellen. Beide Rückgabewerte haben das gleiche Vorzeichen wie x.
>>> math.modf(3.14) (0.1400001, 3.0) >>>
Hier sieht man einen der gefürchten Rundungsfehler bei floats.
`**math.pow(*x*, *y*)**`
Gibt x als Potenz von y zurück.
>>> math.pow(2, 8) 256.0 >>>
`**math.sqrt(*x*)**`
Gibt die Quadratwurzel von x zurück.
>>> math.sqrt(2) 1.414214 >>>
`**math.trunc(*x*)**`
ergibt eine ganze Zahl, wobei x gegen 0 gerundet wird.
>>> math.trunc(3.14) 3 >>> math.trunc(-3.14) -3 >>>
- Ausserdem die Konstanten:**
`**math.e**`
Die Basis der natürlichen Logarithmen.
`**math.pi**`
Die Kreiszahl PI, mit begrenzter Genauigkeit.
>>> math.pi 3.141593 >>>
- Rechnen mit float führt manchmal zu erstaunlichen Ergebnissen.
Da `float` nur eine begrenzte Auflösung bietet, kommt es gelegentlich zu Rundungsfehlern.
>>> 10.99999 10.99999 >>> 10.999999 11.0
> Wenn insgesamt mehr als 7 Stellen vorhanden sind wird die Fließkommazahl gerundet! >
Der Übergang zum Aufrunden liegt aber bei 0.0000006:
>>> 9.99999959 # 9 Stellen 9.999999 >>> 9.9999996 # 8 Stellen 10.0 >>> # Noch präzieser: >>> 9.99999959999 # 12 Stellen 9.999999 >>> 9.999999599991 # 13 Stellen 10.0 >>>
So wie es aussieht wird intern mit 12 Stellen gerechnet und dann auf 7 Stellen gerundet.
Ich habe nur sehr selten typische Rundungsfehler in MP gefunden. Die üblichen Beispiele aus dem Internet funktionierten hier nicht.
Eine Abhandlung dazu für Python 3.3 ist hier zu finden: [6](https://py-tutorial-de.readthedocs.io/de/python-3.3/floatingpoint.html) .
- Floats vergleichen.
Aufgrund der Rundungsfehler ist ein direkter Vergleich von floats problematisch. Es wird deshalb empfohlen stattdessen die Abweichung der floats zu ermitteln und zu testen, ob diese geringer als ein zugestandener Fehler ist: `abs(x-y) < eps` .
Man kann auch eine entsprechende Funktion schreiben. Hier ein Beispiel in C:
bool almostEqual (float a, float b)
{
return fabs(a - b) <= FLT_EPSILON;
}
nan
Nan steht für Not a Number, also keine Zahl und existiert nur für floats. Es Bedeutet, das hier kein Wert zur Verfügung steht.
>>> n = float('nan')
>>> n
nan
>>> n = float('Nan')
>>> n
nan
>>> n = float('NaN')
>>> n
nan
>>> n = float('NAN')
>>> n
nan
>>>
Mit der folgenden Funktion aus dem Modul math kann darauf getestet werden:
`**math.isnan(*x*)**`
Gibt True zurück, wenn x nicht eine Zahl ist
>>> a = 42
>>> n = float('nan')
>>> math.isnan(a)
False
>>> math.isnan(n)
True
>>>
> ‘==’ funktioniert nicht bei nan! >
>>> n = float('nan')
>>> m = float('nan')
>>> n == m
False
>>> n is m
False
>>> id(n)
1073493184
>>> id(m)
1073493216
>>>
Nan wird verwendet wenn ...