Toleranzen von Double und Float
Verfasst: 26.12.2023 17:07
Ein Auszug aus der PB Hilfe
Der genaue Wertebereich, in dessen Rahmen beim Rechnen mit Floats und Doubles korrekte Ergebnisse erzielt werden, sieht wie folgt aus:
Float: +- 1.175494e-38 bis +- 3.402823e+38
Double: +- 2.2250738585072013e-308 bis +- 1.7976931348623157e+308
D.h. man müsste bei Double auf Toleranzen von < 3e-308 kommen
Versuche ich, dass direkt berechnen zu lassen, d.h. ab wann eine 1 noch als 1 erkannt wird, kommt man nur auf etwa 1e-16.
genau 0.000 000 000 000 000 111 022 3025 ; ca. 1.11e-16
Wo liegt da das Problem? Übrigens die Methode, die Genauigkeit zu berechnen stammt als alten Fortran Codes als die
x87 Coprozessoren aufkamen.
Der genaue Wertebereich, in dessen Rahmen beim Rechnen mit Floats und Doubles korrekte Ergebnisse erzielt werden, sieht wie folgt aus:
Float: +- 1.175494e-38 bis +- 3.402823e+38
Double: +- 2.2250738585072013e-308 bis +- 1.7976931348623157e+308
D.h. man müsste bei Double auf Toleranzen von < 3e-308 kommen
Versuche ich, dass direkt berechnen zu lassen, d.h. ab wann eine 1 noch als 1 erkannt wird, kommt man nur auf etwa 1e-16.
genau 0.000 000 000 000 000 111 022 3025 ; ca. 1.11e-16
Wo liegt da das Problem? Übrigens die Methode, die Genauigkeit zu berechnen stammt als alten Fortran Codes als die
x87 Coprozessoren aufkamen.
Code: Alles auswählen
Procedure.d CalcDoublePrecision()
Protected.i I, N
Protected.d FPr, res
; IT CARRIES OUT AN APPROXIMATION OF MACHINE PRECISION
FPr = 1.0
N = 2
While (1.0 + FPR) > 1.0
FPr = 0.5 * FPr
; The For Next is only to confuse the copiler optimation
; especally for the C-Backend. It's to force the compiler
; to copy the FPr variable to the memory. Because the internal
; precision of floating Point registers might be higher.
; x32 and x64 (Floating Point calculation precision is 80 Bit)
; We need the precsion what can be saved in memory
; For I = 1 To N
; res = res + FPR * I
; Next
Wend
res + 1
ProcedureReturn FPr
EndProcedure
Procedure.i EQd(V1.d, V2.d, Tol.d) ; As Boolean
If Abs(V1 - V2) <= Tol
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Debug CalcDoublePrecision()
Debug StrD(CalcDoublePrecision(),32)
#Tol = 0.0000000000000002
; 0.0000000000000001110223025 ; 1.11e-16
Define TOL.d = CalcDoublePrecision()
Define x.d = 1
;Define y1.d = 1.0000000000000001
Define y1.d = 1.0000000000000001
Define y2.d = 1.0000000000000002
Define y3.d = 1.0000000000000003
Define y4.d = 1.0000000000000004
Define y5.d = 1.0000000000000005
Debug Bool(EQd(x,y1,TOL))
Debug Bool(EQd(x,y2,TOL))
Debug Bool(EQd(x,y3,TOL))
Debug Bool(EQd(x,y4,TOL))
Debug Bool(EQd(x,y5,TOL))