In VB.Net werden bei einem Überlauf der Gleitkomma-Arithmetik keine Ausnahmen ausgelöst. Auch die mathematischen Funktionen für Gleitkomma-Variable, die in VB.Net enthalten sind, lösen beim Auftreten von Sonderwerten - z.B. infolge von 'Überlauf' oder ungültigen Argumenten - keinen Fehler aus, sondern liefern einen IEEE-Sonderwert zurück. Die einzelnen Funktionen zeigen ein spezifisches Verhalten im Hinblick auf diese Sonderbedingungen. Dabei ist zu unterscheiden, ob Sonderwerte im Argument oder in der Rückgabe einer Methode auftreten. Im einzelnen sind folgende Fälle anzutreffen:
Die VB-Dokumentation der Methoden informiert zwar über dieses spezifische Verhalten, aber nicht (vollständig) bei allen Funktionen, die es betrifft. Besonders problematisch ist der Fall, wenn ein 'Infinity'-Argument als Funktionsrückgabe einen gültigen Double-Wert liefert. Das betrifft die Funktionen Atan, Atan2, TanH, Log(,), Exp, Pow, IEEERemainder. Hinweis zum Auftreten von IEEE-Sonderwerten bei Gleitkomma-Operationen: Hinweis zum Auftreten von IEEE-Sonderwerten bei Datentyp-Konvertierungen: Hinweis zum Auftreten von IEEE-Sonderwerten bei den VB-Finanz-Funktionen: Die Klasse 'sMath' Die Klasse 'sMath' kapselt die Aufrufe der mathematischen Funktionen, die in der statischen Klasse 'Math' des Namespace 'System' enthalten sind. Zusätzlich sind die beiden Funktionen 'Int' und 'Fix' (Namespace 'Visualbasic') gekapselt. Um die Klasse - nach der Hinzufügung zu einem Projekt - zu verwenden, sind im Quellcode lediglich die Aufrufe Math.irgendeineFunktion() zu ersetzen durch sMath.irgendeineFunktion(). Die öffentlichen Methoden von 'sMath' sind mit dem Schlüsselwort 'SHARED' deklariert, d.h. es muss keine Instanz der Klasse erstellt werden, um sie aufzurufen. Die Math-Funktionen für Ganzzahl-Variable und die Überladungen für den Datentyp 'Decimal' sind in 'sMath' ebenfalls gekapselt, damit in der Testphase eines Programms im Quellcode meist ein globales, reversibles Ersetzen von 'Math.' durch 'sMath.' möglich ist. Falls beim Aufruf einer Methode ein IEEE-Sonderwert auftritt, wird der auffangbare Fehler 5 (= 'ArgumentException') ausgelöst. Die Verwendung der Funktionen in 'sMath' (statt direkt in 'Math') führt ungefähr zu einer Verdoppelung des Rechenzeitbedarfs. Die Code-Kommentare zu den einzelnen Funktionen in der Klasse 'sMath' enthalten weitere Details bezüglich IEEE-Sonderwerten. ' =============================================================== ' Klasse 'sMath' für mathematische VB-Gleitkomma-Methoden ' =============================================================== ' Kapselung des Zugriffs auf Methoden der Klasse 'System.Math' ' Sprache: VB.Net 2005 ' Es wird in allen Ausnahmefällen und beim Auftreten ' von IEEE-Sonderwerten der Fehler 5 ausgelöst ' (Message: Procedure Argument is not valid) ' Fehler können aufgefangen werden z.B. durch: ' Try ' Gleitkomma-Methoden ..... ' catch ex as ArgumentException ' msgbox ex.Message ' msgbox ex.Source ' End Try Public NotInheritable Class sMath ' IEEE-Sonderwert 'not a number' Const cNan As Double = System.Double.NaN ' Variable für Aufruf-Registrierung / Fehlermeldung Private Shared gFunction As String ' gerufene Funktion Private Shared gArg1 As Double ' erstes Argument Private Shared gArg2 As Double ' zweites Argument oder cNan Private Shared Function IsException(ByVal arg As Double) As Boolean ' Falls in 'arg' ein Sonderwert vorliegt, ' wird der Fehler 5 ausgelöst If Double.IsInfinity(arg) Or Double.IsNaN(arg) Then ' Auslösung des Fehlers Call DoException() IsException = True End If End Function Private Shared Sub DoException() ' Auslösung des Fehlers 5 'AgumentException' Dim err_message As String ' Fehlerobjekt säubern Err.Clear() ' Fehlermeldung erstellen err_message = "Procedure Argument is not valid: " err_message += (gFunction + "(" + CStr(gArg1)) If Not Double.IsNaN(gArg2) Then err_message += (", " + CStr(gArg2)) End If err_message += ")" ' Fehler 'ArgumentException' auslösen Err.Raise(5, "sMath." + gFunction, err_message) End Sub Public Shared Function Abs(ByVal arg As Double) As Double ' Hinweis: Für diese Funktion sind in System.Math ' sieben Überladungen definiert (div. Datentypen) ' zusätzlich benötigte Überladungen ' ggf. in 'sMath' ergänzen ' Infinity-Werte im Argument müssen abgefangen werden gFunction = "Abs" gArg1 = arg : gArg2 = cNan If Not IsException(arg) Then Abs = System.Math.Abs(arg) End If End Function Public Shared Function Sign(ByVal arg As Double) As Double ' vgl. Kommentar zur Funktion 'Abs' ' Vorzeichen von +/-unendlich müssen ggf. abgefangen werden gFunction = "Sign" gArg1 = arg : gArg2 = cNan If Not IsException(arg) Then Sign = System.Math.Sign(arg) End If End Function Public Shared Function Max(ByVal arg1 As Double, ByVal arg2 As Double) As Double ' vgl. Kommentar zur Funktion 'Abs' ' die Eingabeparameter müssen geprüft werden, ' z.B. weil Vergleiche gegen '-unendlich' abzufangen sind gFunction = "Max" gArg1 = arg1 : gArg2 = arg2 If Not IsException(arg1) And Not IsException(arg2) Then Max = System.Math.Max(arg1, arg2) End If End Function Public Shared Function Min(ByVal arg1 As Double, ByVal arg2 As Double) As Double ' vgl. Kommentar zur Funktion 'Abs' ' die Eingabeparameter müssen geprüft werden, ' z.B. weil Vergleiche gegen '+unendlich' abzufangen sind gFunction = "Min" gArg1 = arg1 : gArg2 = arg2 If Not IsException(arg1) And Not IsException(arg2) Then Min = System.Math.Max(arg1, arg2) End If End Function Public Shared Function Sin(ByVal arg As Double) As Double ' Math.Sin liefert bei Infinity-Argument NaN zurück gFunction = "Sin" gArg1 = arg : gArg2 = cNan Sin = System.Math.Sin(arg) IsException(Sin) End Function Public Shared Function Cos(ByVal arg As Double) As Double ' Math.Cos liefert bei Infinity-Argument NaN zurück gFunction = "Cos" gArg1 = arg : gArg2 = cNan Cos = System.Math.Cos(arg) IsException(Cos) End Function Public Shared Function Tan(ByVal arg As Double) As Double ' Argumente sehr nahe bei PI/2 erzeugen zwar theoretisch ' Infinity-Werte, praktisch entstehen aber gültige hohe ' Double-Ausprägungen ' --> die werden deshalb zusätzlich abgefangen gFunction = "Tan" gArg1 = arg : gArg2 = cNan Tan = System.Math.Tan(arg) If System.Math.Abs(Tan) > 10000000000.0 Then ' PI/2 Call DoException() Else IsException(Tan) End If End Function Public Shared Function Asin(ByVal arg As Double) As Double ' Exception insbesondere, wenn abs(arg) > 1 gFunction = "Asin" gArg1 = arg : gArg2 = cNan Asin = System.Math.Asin(arg) IsException(Asin) End Function Public Shared Function Acos(ByVal arg As Double) As Double ' Exception insbesondere, wenn abs(arg) > 1 gFunction = "Acos" gArg1 = arg : gArg2 = cNan Acos = System.Math.Acos(arg) IsException(Acos) End Function Public Shared Function Atan(ByVal arg As Double) As Double ' Exception insbesondere dann, wenn abs(arg) = PI/2 gFunction = "Atan" gArg1 = arg : gArg2 = cNan Atan = System.Math.Atan(arg) IsException(Atan) End Function Public Shared Function Atan2(ByVal y As Double, ByVal x As Double) As Double ' x,y: kartesische Koordinaten ' Steigung einer Gerade vom Ursprung mit Schnitt x,y ' Reihenfolge der Argumente ungewöhnlich (y,x)!! ' Die Argumente müssen explizit geprüft werden !! ' (ggf. wird sonst bei 'Infinity' der Wert PI/2 zurückgegeben) gFunction = "Atan2" gArg1 = y : gArg2 = x If Not IsException(y) And Not IsException(x) Then Atan2 = System.Math.Atan2(y, x) IsException(Atan2) End If End Function Public Shared Function SinH(ByVal arg As Double) As Double ' Math:SinH arg = 'Infinity' gibt 'Infinity' zurück gFunction = "SinH" gArg1 = arg : gArg2 = cNan SinH = System.Math.Sinh(arg) IsException(SinH) End Function Public Shared Function CosH(ByVal arg As Double) As Double ' Math.CosH arg = 'Infinity' gibt 'Infinity' zurück gFunction = "CosH" gArg1 = arg : gArg2 = cNan CosH = System.Math.Cosh(arg) IsException(CosH) End Function Public Shared Function TanH(ByVal arg As Double) As Double ' Math.TanH gibt bei 'Infinity'-Agument +/-1 zurück ' das Argument muss deshalb explizit geprüft werden gFunction = "TanH" gArg1 = arg : gArg2 = cNan If Not IsException(arg) Then TanH = System.Math.Tanh(arg) IsException(TanH) End If End Function Public Shared Function Log(ByVal arg As Double) As Double ' Math.Log: Argumente < 0 erzeugen Soderwert 'Nan' ' Arg = 0 ---> NegativeInfinity gFunction = "Log" gArg1 = arg : gArg2 = cNan Log = System.Math.Log(arg) IsException(Log) End Function Public Shared Function Log(ByVal arg As Double, ByVal base As Double) As Double ' Math.Log(,): Log(1, PositiveInfinity) --> 0 ' Der Base-Parameter muss deshalb explizit geprüft werden gFunction = "Log" gArg1 = arg : gArg2 = base If IsException(base) Then Exit Function Else Log = System.Math.Log(arg, base) IsException(Log) End If End Function Public Shared Function Log10(ByVal arg As Double) As Double ' Argumente < 0 lösen NaN aus ' Argument = 0 ---> NegativeInfinity gFunction = "Log10" gArg1 = arg : gArg2 = cNan Log10 = System.Math.Log10(arg) IsException(Log10) End Function Public Shared Function Exp(ByVal arg As Double) As Double ' exp(-unendlich) --> '0' ' das Argument muss deshalb explizit kontrolliert werden gFunction = "Exp" gArg1 = arg : gArg2 = cNan If Not IsException(arg) Then Exp = System.Math.Exp(arg) IsException(Exp) End If End Function Public Shared Function Sqrt(ByVal arg As Double) As Double ' Math.SQRT: erzeugt bei negativem Argument NaN ' arg = PositiveInfinity --> PositiveInfinity gFunction = "Sqrt" gArg1 = arg : gArg2 = cNan Sqrt = System.Math.Sqrt(arg) IsException(Sqrt) End Function Public Shared Function Pow(ByVal arg As Double, _ ByVal power As Double) As Double ' bei dieser Funktion müssen die Parameter ' geprüft werden, weil Infinity-Argumente im Pow-Resultat ' gültige Werte liefern können (vgl. VB-Doku) gFunction = "Pow" gArg1 = arg : gArg2 = power If Not IsException(arg) And Not IsException(power) Then Pow = System.Math.Pow(arg, power) IsException(Pow) End If End Function Public Shared Function Ceiling(ByVal arg As Double) As Double ' definiert durch: IEEE Standard 754, section 4. ' Returns the smallest integer greater than or ' equal to the specified double-precision number. ' Math.Ceiling würde Infinity-Argumente zurückgeben gFunction = "Ceiling" gArg1 = arg : gArg2 = cNan Ceiling = System.Math.Ceiling(arg) IsException(Ceiling) End Function Public Shared Function Ceiling(ByVal arg As Decimal) As Decimal ' der Vollständigkeit halber .... ' unklar, weshalb die IEEE-Konvention bei diesem Datentyp ' angewendet wird Ceiling = System.Math.Ceiling(arg) End Function Public Shared Function Floor(ByVal arg As Double) As Double ' Math.Floor: ermittelt den ganzzahligen Wert <= arg ' Infinity-Argument ---> Infinity gFunction = "Floor" gArg1 = arg : gArg2 = cNan Floor = System.Math.Floor(arg) IsException(Floor) End Function Public Shared Function Floor(ByVal arg As Decimal) As Decimal ' der Vollständigkeit halber .... ' ermittelt den ganzzahligen Wert <= arg Floor = System.Math.Floor(arg) End Function Public Shared Function Truncate(ByVal arg As Double) As Double ' Truncate rounds to the nearest integer towards zero ' Infinity-Argumente werden sonst zurückgegeben gFunction = "Truncate" gArg1 = arg : gArg2 = cNan Truncate = System.Math.Truncate(arg) IsException(Truncate) End Function Public Shared Function Truncate(ByVal arg As Decimal) As Decimal ' der Vollständigkeit halber .... ' Truncate rounds to the nearest integer towards zero Truncate = System.Math.Truncate(arg) End Function Public Shared Function IEEERemainder(ByVal x As Double, ByVal y As Double) As Double ' Returns the remainder resulting from the division of a ' specified floating-point number by another specified number ' definiert durch: ANSI/IEEE Std 754-1985 Section 5.1 ' IEEERemainder akzeptiert im 2. Argument Infinity-Werte und ' gibt dannn das erste Argument zurück ' --> Argumente explizit prüfen gFunction = "IEEERemainder" gArg1 = x : gArg2 = y If Not IsException(x) And Not IsException(y) Then IEEERemainder = System.Math.IEEERemainder(x, y) IsException(IEEERemainder) End If End Function Public Shared Function Round(ByVal arg As Double, _ Optional ByVal digits As Integer = 0, _ Optional ByVal mode As System.MidpointRounding _ = MidpointRounding.ToEven) As Double ' Die Funktion Math.Round ist mehrfach überschrieben ' Die Funktion sMath.Round löst bei unbrauchbaren ' Parametern immer den Fehler 'ungültiges Argument' aus gFunction = "Round" gArg1 = arg : gArg2 = CDbl(digits) If digits < 0 Or digits > 15 Then ' Digits nicht im Bereich 0-15 Call DoException() ElseIf mode <> MidpointRounding.AwayFromZero And _ mode <> MidpointRounding.ToEven Then ' ungültiger Rundungs-Modus (nur 0/1 akzeptabel) Call DoException() Else Round = System.Math.Round(arg, digits, mode) ' Sonderwerte abfangen IsException(Round) End If End Function Public Shared Function Round(ByVal arg As Decimal, _ Optional ByVal digits As Integer = 0, _ Optional ByVal mode As System.MidpointRounding _ = MidpointRounding.ToEven) As Decimal ' überladene Funktion für Decimal-Werte ' implizite Ganzzahl-Arithmetik: ' ---> Fehler werden von Math.Round ausgelöst Round = Math.Round(arg, digits, mode) End Function ' ================================================================= ' Math-Funktionen für Ganzzahlarithmetik ' Die Ganzzahlarithmetik löst Fehler aus ' ================================================================= Public Shared Function BigMul(ByVal x As Integer, ByVal y As Integer) As Long ' Der Vollständigkeit halber ... BigMul = System.Math.BigMul(x, y) End Function Public Shared Function DivRem(ByVal divident As Integer, _ ByVal divisor As Integer, ByRef remainder As Integer) As Integer ' Der Vollständigkeit halber ... DivRem = System.Math.DivRem(divident, divisor, remainder) End Function Public Shared Function DivRem(ByVal divident As Long, _ ByVal divisor As Long, ByRef remainder As Long) As Long ' Der Vollständigkeit halber ... DivRem = System.Math.DivRem(divident, divisor, remainder) End Function ' ================================================================= ' Rückgabe der Konstanten, die in System.Math deklariert sind ' ================================================================= Public Shared Function PI() As Double ' Der Vollständigkeit halber ... PI = System.Math.PI End Function Public Shared Function E() As Double ' Der Vollständigkeit halber ... E = System.Math.E End Function ' ================================================================= ' 2 Funktionen aus 'Microsoft.Visualbasic' ' ================================================================= Public Shared Function Fix(ByVal arg As Double) As Double ' MS.VB.Fix gibt IEEE-Sonderwerte im Argument zurück ' Fix ist 7x überladen ' zusätzlich erforderliche Überladungen ggf. hinzufügen gFunction = "Fix" gArg1 = arg : gArg2 = cNan Fix = Microsoft.VisualBasic.Fix(arg) IsException(Fix) End Function Public Shared Function Int(ByVal arg As Double) As Double ' MS.VB.Int gibt IEEE-Sonderwerte im Argument zurück ' vgl. Fix gFunction = "Int" gArg1 = arg : gArg2 = cNan Int = Microsoft.VisualBasic.Int(arg) IsException(Int) End Function End Class ' ================================================================= ' Ende der Klasse 'sMath' ' ================================================================= Dieser Tipp wurde bereits 11.471 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevISDN 1.0 Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats Januar 2025 Dieter Otter Zeilen einer MultiLine-TextBox ermitteln (VB.NET) Dieser Zipp zeigt, wie man die Zeilen einer MultiLine-TextBox exakt so ermitteln kann, wie diese auch in der TextBox dargestellt werden. Neu! sevEingabe 3.0 Einfach stark! Ein einziges Eingabe-Control für alle benötigten Eingabetypen und -formate, inkl. Kalender-, Taschenrechner und Floskelfunktion, mehrspaltige ComboBox mit DB-Anbindung, ImageComboBox u.v.m. |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |