# Dezimal zu Binärumrechnung -> Fehler



## Dark Ranger (22. November 2008)

Hi
Kann mir irgendwer sagen, warum es bei folgendem Code zu einem Fehler kommt, wenn eine Zahl >= 32 umgerechnet werden soll:

```
Function Dec2Bin(ByVal lngZahl As Long) As String
    Select Case lngZahl
        Case 0
            Dec2Bin = "0"
        Case 1
            Dec2Bin = "1"
        Case Else
            Dec2Bin = Dec2Bin(lngZahl \ 2) & IIf(lngZahl Mod 2, "1", "0")
    End Select
End Function
```

Folgender Code das gleiche Problem:

```
Private Function Dec2Bin(ByVal Dec As Long) As String
' Von Dezimal in Binaer
Dim Rest As Long
Do
      Rest = Dec Mod 2              ' Den Rest bei einer Division durch 2 errechnen
      Dec2Bin = Rest & Dec2Bin      ' Rest und bishereige Binaer Zahl zusammentun
      Dec = Dec \ 2                 ' Dezimal Zahl durch 2 Teilen
Loop Until Dec = 0                  ' Solange bis Dezimal-Zahl = 0 ist
End Function
```

Fehler ist: Überlauf
Fehlernummer: 6

Wo liegt das Problem? Irgendwo im Speicher oder so?


----------



## JensG (22. November 2008)

Hallo Dark Ranger,

du meinst wohl eher das du keine Zahl größer 32 Bit umrechnen
kannst. Denn eine Dec Zahl größer 32 funktioniert problemlos
mit dem Code.
Erst wenn ich eine Zahl größer 32 Bit (Dec  2147483647) umrechne
kommt ein Überlauf, weil der Typ LONG in VB6 nur bis max -2147483647 bis2147483647 (32Bit) kann. Und unsigned Long gibt es nicht in VB6.

Mehr geht nicht, jedenfalls fällt mir auf die Schnelle nichts ein.
Falls doch würde mich das auch interessieren.

Gruß
Jens


----------



## Dark Ranger (24. November 2008)

Nein so wie ich mir das angeschaut habe übergebe ich die Dezimalzahl 32 und es gibt einen Fehler mit diesem Überlauf.

Mhhh muss ich wohl nochmal schauen.

Folgendes Problem:
Ich will Daten anlegen, die ich über die Binärwerte beliebig miteinander kombinieren kann.

Also:
1. Wert: 1 -> test
2. Wert: 10 -> test1
3. Wert 100 -> test2

Nun weiß ich zum beispiel bei dem Code: 101, dass test und test2 ausgewählt sind.
Im moment Selektiere ich den höchsten Wert aus der Tabelle, rechne das ganze in Dezimal um, multipliziere es mit 2 und rechne es wieder in Binär, habe auch alles überprüft und es werden die richtigen Sachen berechnet usw. allerdings gibt es einen Fehler sobald der Wert >= 32 ist.

Hat irgendwer einen Lösungsvorschlag? Den Quellcode habe ich gerade nicht zur Hand, leider.


----------



## JensG (24. November 2008)

Hallo Dark Ranger,

also wie schon gesagt, die von dir geposteten Functions funktionieren
beide wunderbar mit der Dezimalzahl 32 und auch größer.

Da musst du woanders einen Fehler haben und ohne Code zu sehen
wird es schwer diesen zu finden.

Die Idee an sich ist nicht schlecht mit den Bitkombinationen.
Ich mache das auch des öfteren.
Beachte aber das du an Grenzen stoßen wirst, denn mehr als 32 
mögliche Werte funktionieren nicht wegen 32 Bit Long.

Jens


----------



## Dark Ranger (24. November 2008)

32 Werte sind glaube ich schon ausreichend.

Werde meinen Code nochmal durchschauen, habe ewig nichts mehr mit VB6 oder VBA gemacht. Bisschen was ist hängen geblieben. Aber eigentlich programmiere ich nur noch in PHP oder JAVA, deswegen ist die Syntax Umstellung manchmal ein bisschen schwierig.

Und auf PHP wollte ich nicht zurückgreifen, da es ein Programm für nur eine Person ist. JAVA ist mir dafür auch zu oversized und ich müsste mich erstmal mit den Datenbank Connections rumschlagen. Access scheint genau das richtige zu sein, auch wenn ich es nicht mag ^^


----------



## Dark Ranger (24. November 2008)

Hier ist mein Code mit dem ich es schaffe 10 Datensätze anzulegen, danach ist Schluß und es kommt der Fehler wie oben:


```
Option Compare Database
Private Const binärBasis As Byte = 2

Private Sub abort_Click()
    Me.Visible = False
End Sub

Private Sub saveArt_Click()
    On Error GoTo Fehler
    Dim db As DAO.Database
    Dim result As DAO.Recordset
    Dim strSQL As String
    Dim Zahl As Long
    Dim cache As Variant
    
    If Not Trim(art.Value) = "" Then
        Set db = CurrentDb
        
        strSQL = "SELECT MAX(Nummer) AS HighArt FROM Art"
        
        Set result = db.OpenRecordset(strSQL)
        
        cache = result!HighArt
        
        If IsNull(cache) Then
            Zahl = 0
        Else
            Zahl = cache
        End If
        
        Zahl = Dec2Bin(nextValue(Bin2Dec(Zahl)))
        strSQL = "INSERT INTO Art(Nummer, Art) VALUES ('" & Zahl & "','" & Trim(art.Value) & "')"
        db.Execute (strSQL)
    End If
    GoTo Ende
Fehler:
    MsgBox "Fehler: " & Err.Description & " Nummer: " & Err.Number
    GoTo Ende
Ende:
End Sub

Private Function nextValue(Zahl As Long) As Long
    If Zahl = 0 Then
        nextValue = 1
    ElseIf Zahl = 1 Then
        nextValue = 2
    Else
        nextValue = Zahl * 2
    End If
End Function

Private Function Bin2Dec(ByVal Bin As String) As Long
' Von Binaer nach Dezimal umrechnen
Dim i As Long, lngLen As Long
lngLen = Len(Bin)                   ' Länge der Binärzahl
For i = lngLen To 1 Step -1         ' Für jede Stelle die Schleife durchgehen
     Bin2Dec = Bin2Dec + IIf(Mid$(Bin, i, 1) = "1", 2 ^ (lngLen - i), 0)
                                    ' umrechnen in Dezimal (siehe Erklärung oben)
Next i
End Function
 
Private Function Dec2Bin(ByVal Dec As Long) As String
' Von Dezimal in Binaer
Dim Rest As Long
Do
      Rest = Dec Mod 2              ' Den Rest bei einer Division durch 2 errechnen
      Dec2Bin = Rest & Dec2Bin      ' Rest und bishereige Binaer Zahl zusammentun
      Dec = Dec \ 2                 ' Dezimal Zahl durch 2 Teilen
Loop Until Dec = 0                  ' Solange bis Dezimal-Zahl = 0 ist
End Function
```

Die Tabelle sieht wie folgt aus:

```
ID -> AutoWert -> Primärschlüssel
Nummer -> Zahl -> Long Integer (habe auch schon Text usw. versucht, keine Besserung)
Art -> Text
```

Jemand eine Idee woran es liegen könnte?

Edit:
Bei den 10 Datensätzen klappt alles wunderbar mit dem einfügen der Binären Zahlen


----------



## JensG (24. November 2008)

Hallo Dark Ranger,

aus deinem Code wird nicht so richtig ersichtlich wozu du
eigentlich die Umrechnung von Dec zu Bin und umgekehrt
benötigst.

Was genau soll im Feld Nummer gespeichert werden ?
Einen Dezimalwert oder einen Binärwert der mehrere Dezimalwerte
beinhalten kann (1,2,4,8,16 usw.)

Die Zeile
Zahl = Dec2Bin(nextValue(Bin2Dec(Zahl)))

macht irgendwie überhaupt keinen Sinn und da kommt mit
Sicherheit auch der falsche Wert raus.

Wenn Zahl = Dec2Bin sein soll muss Zahl schon mal als String
deklariert werden denn ein Long kann nicht 0101 sein.
Da würde 101 rauskommen und das wäre ja schon falsch.
Dec2Bin gibt ja auch richtigerweise einen String zurück.

Ich habe den Sinn noch nicht ganz verstanden, aber wenn du
genau sagst was du willst kann ich sicher helfen.

Da sind wahrscheinlich noch mehr Bugs drin, sag mal genau was du willst.

Jens


----------



## Dark Ranger (24. November 2008)

In Nummer stehen Binärwerte.

0101 wird nie vorkommen, da nur 0,1,2,4,8,16 usw. in Binärschreibweise vorkommen können.

Ich hole mir am Anfang den höchsten Wert aus der Tabelle, rechne diesen in Dezimal um, nehme den nächsten Wert und rechne das ganze wieder nach Binär.

Wäre im Moment bestimmt auch durch eine Binärverschiebung oder soetwas möglich, sodass ich gar nicht umrechnen brauche, aber so war es für mich einfacher zu rechnen.

Die ganze Prozedur wird dafür benötigt einen neuen Datensatz anzulegen, dieser bekommt halt immer den höchsten Wert und wird dann in der Datenbank eingetragen.


----------



## JensG (24. November 2008)

Hallo Dark Ranger,

schaue dir mal den Code an.
Ist natürlich jetzt etwas angepasst, da ich das mit VB6 getestet habe.
So funktioniert es und es wird immer bei einem neuen Datensatz
0        für 0 
1        für 1 
10      für 2 
100    für 4
1000  für 8 

aber du kombinierst ja nichts und von daher
verstehe ich nicht wofür das ganze in Binär gut sein soll. 



```
Private Sub saveArt_Click()
    
    On Error GoTo Fehler
    Dim db As DAO.Database
    Dim result As DAO.Recordset
    Dim strSQL As String
    Dim Zahl As String
    
    Dim art As String
    art = "Test"
        
        Set db = DAO.OpenDatabase("C:\test.mdb")
        
        strSQL = "SELECT MAX(Nummer) AS HighArt FROM Art"
        
        Set result = db.OpenRecordset(strSQL)
        
               
        If IsNull(result!HighArt) Then
            Zahl = 0
        Else
            Zahl = nextValue(Bin2Dec(result!HighArt))
        End If
        
              
        strSQL = "INSERT INTO Art(Nummer, Art) VALUES ('" & Dec2Bin(Zahl) & "','" & Trim(art) & "')"
        db.Execute (strSQL)
   
   
   
    GoTo Ende
Fehler:
    MsgBox "Fehler: " & Err.Description & " Nummer: " & Err.Number
    GoTo Ende
Ende:

End Sub
```

Jens


----------



## Dark Ranger (24. November 2008)

Die Kombination der Werte wird es erst in einem anderen Formular geben.

Werde deinen Code morgen mal ausprobieren, danke


----------



## Dark Ranger (25. November 2008)

Habe das ganze nun einmal getestet, es gibt keinen Fehler mehr, allerdings hört nach 10 Einträgen die Binärzahl auf und es wird nichts mehr in die Datenbank eingetragen, nur noch die Art wird eingetragen, die Nummer nicht mehr.

Ich habe keine Ahnung woran es liegt, es ist schon sehr seltsam wie ich finde


----------



## JensG (25. November 2008)

Hallo Dark Ranger,

ich kann das hier bei dem an dich geposteten Code nicht nachvollziehen.

Ich kann hier 20 oder 30 Datensätze hinzufügen.

Ahhh...
Ich vermute du hast das Feld Nummer in der Access DB noch auf Integer stehen,
das muss TEXT 255 sein ! Ein Integer kann diese Datenmenge nicht speichern !

Jens


----------



## Dark Ranger (25. November 2008)

Jo danke nun funktioniert es, ich kann 31 Datensätze hinzufügen, dies sollte für den ersten Moment reichen, sollte ich doch noch mehr brauchen, muss ich mir noch irgendwas überlegen

Danke


----------



## Dark Ranger (25. November 2008)

Hi

Ich habe nun ein neuer Problem!
Kann ich ein Formular noch ändern in der Form_Load Methode?

Ich würde nämlich gerne Checkboxen(oder soetwas) hinzufügen, je nach Anzahl der eingespeicherten Einträge in der oben genannten Tabelle.

Am besten wäre es natürlich, wennn mir diese Checkboxen die Nummer aus der Tabelle zurückliefern, wenn sie angeklickt sind. Weiß nicht ob das möglich ist.

Das durchgehen der einzelnen Zeilen in der Tabelle ist kein Problem, allerdings weiß ich nicht ob man nachträglich etwas zu einem Formular hinzufügen kann.

Edit:
Ich habe jetzt nochmal ein bisschen rumgestöbert und ich glaube dies ist gar nicht so einfach wie ich mir das vorstelle, selbst die Größe eines Fensters dynamisch zu verändern scheint schon etwas komplizierter zu sein


----------



## ronaldh (25. November 2008)

Dann lies Dir mal diesen Tipp durch.

Und mit der Height und Width Eigenschaft kannst Du die Größe der Form ändern.

Grüsse
ronaldh


----------



## Dark Ranger (25. November 2008)

Wie verändere ich denn die Größe des Formulars? Ich habe das nun mal mit Form.InsideHeight versucht, funktioniert eigentlich auch, bis dahin, dass ich immer 2000 hinzuaddiere, er aber nur 1995 nimmt.

Will ich nun einen Button (der ist schon vorhanden) auch verschieben, sodass er unten am Formular bleibt, dann gibt es einen Fehler, obwohl ich button.top auch nur um 2000 erhöhe, allerdings kommt dann:
"Das Steuerelement oder Unterformular ist zu groß..."

Habe ich gedacht, ok dass eine wird nur 1995 vergrößert das andere verschiebe ich 2000, verschiebe ich den Button allerdings nur 100 oder so, taucht der Fehler beim zweiten oder dritten durchlauf auch auf -.-


```
Set result = db.OpenRecordset(strSQL)
    If result.RecordCount > 0 Then
        result.MoveFirst
        Form.InsideHeight = 2250
        Do While Not result.EOF
            Form.InsideHeight = Form.InsideHeight + 2000
            Call saveMeeting.Move(saveMeeting.Left, saveMeeting.Top + 100)
            'saveMeeting.Top = saveMeeting.Top + 2000
            result.MoveNext
        Loop
        
    End If
```

Jemand nen Vorschlag?


----------



## ronaldh (26. November 2008)

Womit arbeitest Du eigentlich?

InsideHeight/InsideWidth gibt es meines Wissens nach nur in VBA, ist dort jedoch zur Laufzeit schreibgeschützt. Die Größe einer Form änderst Du mit Height und Width.


----------



## Dark Ranger (26. November 2008)

Arbeite mit VBA und habe dort kein Height und Width.

Wenn ich Inside Height anpasse ändert sich aber die Größe des Formulars.


----------



## ronaldh (26. November 2008)

Zwischen den einzelnen VBA's gibt es Unterschiede, deswegen hilft die Aussage "VBA" nicht wirklich.

Ich habe es mit VBA im Excel 2003 geprüft, da hat die Form sowohl eine Height als auch eine Width Eigenschaft, die man auch ändern kann, InsideHeight / InsideWidth sind dagegen schreibgeschützt zur Laufzeit.

Ansonsten ist es doch vielleicht sinnvoller, wenn Du den Button (der ja unten an der Form bleiben soll), an die InsideHeight-Eigenschaft bindest, und nicht einfach verschiebst, z.B.:


```
Button.Top = Form.InsideHeight - (Button.Height + 25)
```


----------



## Dark Ranger (27. November 2008)

Das habe ich auch schon versucht, funktioniert allerdings auch nicht.

Nutze VBA in Zusammenhang mit Acess 2002 meiner Meinung nach


----------



## ronaldh (27. November 2008)

Ich habe eben zum ersten Mal in VBA für Access geguckt, das ist wirklich vollkommen anders. Wenn ich mit Access-Datenbanken arbeite, spreche ich die von VB6 aus an, das ist doch wesentlich mächtiger. Außerdem nervt mich, dass dort ständig irgendwelche Assistenten hoch kommen, die meine Arbeit machen wollen (vielleicht kann man das ja abschalten).

In der Hilfe habe ich da folgendes Beispiel gefunden, vielleicht hilft es Dir:


```
Sub ResetWindowSize(frm As Form)
    Dim intWindowHeight As Integer
    Dim intWindowWidth As Integer
    Dim intTotalFormHeight As Integer
    Dim intTotalFormWidth As Integer
    Dim intHeightHeader As Integer
    Dim intHeightDetail As Integer
    Dim intHeightFooter As Integer

    ' Determine form's height.
    intHeightHeader = frm.Section(acHeader).Height
    intHeightDetail = frm.Section(acDetail).Height
    intHeightFooter = frm.Section(acFooter).Height
    intTotalFormHeight = intHeightHeader _
        + intHeightDetail + intHeightFooter
    ' Determine form's width.
    intTotalFormWidth = frm.Width
    ' Determine window's height and width.
    intWindowHeight = frm.InsideHeight
    intWindowWidth = frm.InsideWidth

    If intWindowWidth <> intTotalFormWidth Then
        frm.InsideWidth = intTotalFormWidth
    End If
    If intWindowHeight <> intTotalFormHeight Then
        frm.InsideHeight = intTotalFormHeight
    End If
End Sub
```


----------



## Dark Ranger (23. Dezember 2008)

Also das ändern der Fenstergröße funktioniert nun soweit, auch wenn ich die Buttons nicht verschieben kann.



ronaldh hat gesagt.:


> Dann lies Dir mal diesen Tipp durch.
> 
> Und mit der Height und Width Eigenschaft kannst Du die Größe der Form ändern.
> 
> ...



Habe den Tip ausproiert, allerdings sagt er mir, dass es die Add Methode nicht gibt. Arbeite übrigens mit VBA unter Access 97, ich denke dies ist auch das größte Problem.


----------



## ronaldh (5. Januar 2009)

Dark Ranger hat gesagt.:


> Arbeite übrigens mit VBA unter Access 97, ich denke dies ist auch das größte Problem.



Das vermute ich auch. Da kann ich Dir leider nicht helfen, denn das wird sich zu dem von mir verwendeten Access 2003 sicherlich auch noch unterscheiden.

Sorry...


----------

