ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 15.02.2001

Diese Seite wurde zuletzt aktualisiert am 15.02.2001
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Vorzeichenlose Werte

Zurück...


Anzeige

(-hg) mailto:hg_unsigned@aboutvb.de

In Visual Basic sind sie fast unbekannt: vorzeichenlose Datentypen. Lediglich der Datentyp Byte kennt keine negativen Werte. Bei allen anderen Datentypen gibt es sowohl positive als auch negative Werte, die sich den zur Verfügung stehenden Wertebereich teilen müssen. Das bedeutet beispielsweise, dass die größtmögliche Integer-Zahl 32767 ist, obwohl in den 4 zur Verfügung stehenden Bytes auch der Wert 65535 möglich wäre. Betrachtet man die hexadezimale Darstellung des Wertes 32767, nämlich &H7FFF, dann sollte doch eigentlich ein &H7FFF + 1 den Wert &H8000, also 32768 ergeben können. Statt dessen entspricht &H8000 dem Wert -32768. Die weitere Zählung &H8000 + 1 erhöht den Wert allerdings folgerichtig um eins - &H8001 ist -32767.

Für Zahlen und Werte des Datentyps Long gilt im Prinzip dasselbe. Der Unterschied ist lediglich, dass hier 8 Bytes statt deren 4 zur Verfügung stehen. Bei Long-Werten können sie nicht über 2147483647 (&H7FFFFFFF) hinaus zählen: &H7FFFFFFF + 1 wird mit einer Fehlermeldung (Überlauf) quittiert, während als Ergebnis eigentlich &H80000000 wünschenswert wäre.

Bei Integer-Zahlen ist das sicher kein sehr schwerwiegendes Problem. Normalerweise können Sie die Zahl in eine des Datentyps Long konvertieren - und schon können Sie auch weiterzählen und -rechnen. Allerdings gibt es API-Funktionen, die ausdrücklich vorzeichenlose "Short-Integers" (so heißen die VB-Integer etwa in C und vielen anderen Programmiersprachen) in ihren Parametern verlangen oder solche zurückgeben. Sie können hier ohne Schwierigkeiten VB-Integer-Werte verwenden, solange Sie nicht an deren "echtem" Wert interessiert sind. Die Kommunikation von VB mit dem API stört sich nicht daran.

Haben Sie aber einmal einen solchen vorzeichenlosen Wert vorliegen, der den positiven Wertebereich des Integer-Datentyps überschreitet und Ihnen als negative Zahl erscheint, und Sie wollen den echten Wert darstellen, wird Ihnen die Konvertierung des Wertes in einen Long-Wert mittels CLng(Wert) nichts nützen. Zwar können Sie einen Konstant-Wert wie &H8000 als positiven Wert erhalten, indem Sie ausdrücklich das Typkennzeichen "&" anhängen: CLng(&H8000&) wird tatsächlich als 32768 ausgegeben. Doch bei einem in einer Variablen steckenden Wert gibt es dieses Schlupfloch nicht.

Die folgende Konvertierfunktion CIntToUInt hilft Ihnen weiter. Sie prüft, ob der übergebene Wert "noch" positiv ist. Wenn ja, gibt sie ihn unberührt als Long-Wert zurück. Ist er negativ, wird er umgerechnet und als Long-Wert zurückgegeben. Die Umrechnung beruht darauf, dass der tatsächliche Abstand zwischen dem gegebenen &H8000 (= -32768) und dem gewünschten 32768 genau 2 * &H8000& beträgt. Und das gilt natürlich auch für alle weiteren folgenden, höheren Werte bis &HFFFF. Allerdings wird der "glatte" Fall &H8000 hier ausgenommen, da die Umkehrung des Vorzeichens ausreicht und sich die aufwändigere Rechnerei erübrigt.

Public Function CIntToUInt(IntValue As Integer) As Long
  Select Case IntValue
    Case Is < 0
      CIntToUInt = IntValue - &HFFFF0000
    Case &H8000
      CIntToUInt = IntValue * -1
    Case Else
      CIntToUInt = IntValue
  End Select
End Function

Lassen Sie sich nicht davon irritieren, dass hier offensichtlich entgegen der obenstehenden Aussage nicht addiert, sondern subtrahiert wird. VB-intern ist der "Ausgleichswert" ja negativ. Da die Addition eines negativen Wertes eine Subtraktion wäre, müssen wir also den negativen Wert subtrahieren, also tatsächlich addieren.

Das gleiche gilt auch für den Rückwärtsgang dieser Funktion, für die Funktion CUIntToInt, die einen Long-Wert über &H7FFF& wieder in die ("vorzeichenbehaftete", wie man sagt) Darstellung des Integer-Datentyps zurückkonvertiert. Sie beruht auf dem gleichen Prinzip - nur eben umgekehrt:

Public Function CUIntToInt(ByVal LongValue As Variant) As Integer
  Select Case LongValue
    Case Is <= &H7FFF
      CUIntToInt = LongValue
    Case &H8000
      CUIntToInt = LongValue * -1
    Case Else
      CUIntToInt = LongValue + &HFFFF0000
  End Select
End Function

Wie eingangs angedeutet, ergibt sich das gleiche Problem bei Long-Werten, die über den positiven Wertebereich dieses VB-Datentyps hinausreichen. Solange Sie solche Werte nur in Ihrem Programm benötigen, können Sie auf den Variant-Unterdatentyp Decimal ausweichen. Doch wenn es wieder um Übergaben an API-Funktionen und um deren Rückgabewerte geht, hilft Ihnen dieser Ausweg auch wieder nicht weiter.

Analog zu den Konvertierfunktionen für vorzeichenlose Integerwerte können Sie nun auch Konvertierfunktionen für vorzeichenlose Long-Werte erhalten. Sie brauchen lediglich eine "Dimension höher" zu denken.

Public Function CLongToULong(LongValue As Long) As Variant
  Select Case LongValue
    Case Is < 0
      CLongToULong = CDec(LongValue - CDec(&H80000000) * 2)
    Case &H80000000
      CLongToULong = CDec(LongValue) * -1
    Case Else
      CLongToULong = CDec(LongValue)
  End Select
End Function

Public Function CULongToLong(ByVal DecimalValue As Variant) As Long
  Select Case DecimalValue
    Case Is <= &H7FFFFFFF
      CULongToLong = DecimalValue
    Case &H80000000
      CULongToLong = DecimalValue * -1
    Case Else
      CULongToLong = DecimalValue + CDec(&H80000000) * 2
  End Select
End Function

Da der Variant-Unterdatentyp Decimal für VB allerdings nur eine Art "Kuckucksei" darstellt, mit dem er eigentlich intern gar nicht richtig umgehen kann, muss auch der Ausgleichswert erst als Decimal-Wert berechnet werden. Und auch hier wieder gilt die Notwendigkeit der Umkehrung von Addition bzw. Subtraktion des Ausgleichswertes.


Modul modUnsigned (modUnsigned.bas - ca. 1,5 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikels

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche




Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer