Rundungsfehler¶
[1]:
import numpy as np
from floatMemoryRepresentation import float2bin
Problem¶
Wir betrachten folgendes schönes Beispiel zum Rundungsproblem aufgrund der endlichen Digits der Zahlendarstellung:
[2]:
r1 = np.arange(0,0.3,0.1)
r1
[2]:
array([0. , 0.1, 0.2])
ABER:
[3]:
r2 = np.arange(1,1.3,0.1)
r2
[3]:
array([1. , 1.1, 1.2, 1.3])
Was passiert hier?¶
Das Problem besteht darin, dass 0.1 mit endlich vielen Bits nicht exakt dargestellt werden kann. In der Darstellung wird aufgerundet und wir erhalten etwas mehr als 0.1 exakt:
[4]:
float2bin(0.1,length=64)
[4]:
'0011111110111001100110011001100110011001100110011001100110011010'
Mit MPFR können wir 0.1 mit beliebiger Anzahl Bits leicht berechnen (verfügbar mit ‚pip install gmpy2‘):
[5]:
from gmpy2 import mpfr
[6]:
mpfr('0.1',precision=100)
[6]:
mpfr('0.10000000000000000000000000000002',100)
Unter der Verwendung einer 100Bit Darstellung folgt für float(0.1)
die effektive Zahl
[7]:
mpfr(float(0.1),precision=100)
[7]:
mpfr('0.10000000000000000555111512312578',100)
Wird nun 3 mal 0.1 mit 52 Bit addiert so erhält man folgende Zahl binär dargestellt:
[8]:
float2bin(3*0.1,length=64)
[8]:
'0011111111010011001100110011001100110011001100110011001100110100'
Welche jedoch kleiner ist als die 52Bit Binäre Darstellung von 0.3
:
[9]:
float2bin(0.3,length=64)
[9]:
'0011111111010011001100110011001100110011001100110011001100110011'
Im Fall von 1+3*0.1
ist dem nicht so, hier erhalten wir die exakt identische interne 52Bit Darstellung:
[10]:
float2bin(1+3*0.1,length=64)
[10]:
'0011111111110100110011001100110011001100110011001100110011001101'
[11]:
float2bin(1.3,length=64)
[11]:
'0011111111110100110011001100110011001100110011001100110011001101'
Merke: will man in einer while
Schleife inkrementell bis zu einem bestimmten Wert iterieren, wobei das Inkrement dt
Teiler der Grenze T
ist, so muss man sehr vorsichtig mit der Abfrage t < T
sein. Es ist besser t < T + dt/2
zu benutzen.