Umrechnung: Zahlensysteme

  • VB.NET
  • .NET (FX) 4.0

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Umrechnung: Zahlensysteme

    Hallo,
    ich habe folgendes Problem: Es gibt ja die Convert-Funktion mit der man Zahlen vom
    Dezimalsystem in andere Zahlensysteme umrechnen kann und auch wieder zurück.
    Zwischendurch hatte ich zwar eine eigene Methode für diese Umrechnung geschrieben bin dann aber auf diese zurückgekommen.
    Allerdings beschränkt sich diese Umrechnung auf die Zahlensysteme mit den Basen: 10, 2, 8, 16. :(
    Gibt es evtl. eine andere Funktion in Visual Baisc mit der man Zahlen in andere Z.-Systeme umrechnen kann (z.B. für das Pentalsystem)?

    Leo 97 schrieb:

    von Visual Basic
    Nein.
    Nur die von Dir oben genannte.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vorsicht mit den Begriffen: Die Funktionen in der Konvert-Klasse konvertieren nicht von einem zu einem anderen Zahlensystem, sondern sie konvertieren zwischen Datentypen.
    Beispiel:

    Visual Basic-Quellcode

    1. Function Convert.ToString(Integer, Integer) As String
    2. 'Anwendung:
    3. MessageBox.Show(Convert.ToString(13, 2))

    13 ist ein Integer. Dieser Integer wird immer den Wert 13 haben. "13" ist nur die dezimale Repräsentation von diesem Wert. "1101" wäre die binäre Repräsentation, "D" die hexadezimale, etc...
    Die Convert-Funktion rechnet nicht vom dezimalen (oder von irgend einem) Zahlensystem in das angegebene um. Die Funktion gibt einen String zurück, der den angegebenen Wert repräsentiert, und zwar in der Basis, die man angegeben hat.
    Also Convert.ToString(13, 2) gibt den String "1101" zurück. Das ist eine Repräsentation vom Wert 13. Wenn Du als Basis 10 angibst, kommt "13" heraus, was auch eine Repräsentation von 13 ist. Beide haben den selben Wert, es sind nur unterschiedliche Repräsentationen.
    Wenn Du von der Repräsentation zurückkonvertieren willst, musst Du wissen, für welche Basis die Repräsentation bestimmt ist:
    Convert.ToInt32("1101", 2) ergibt wieder den Wert 13. Genauso wie Convert.ToInt32("13", 10) den Wert 13 ergibt.

    Das Problem, das sich hier ergibt, ist der Datentyp, der für die Repräsentation verwendet wird. Strings sind stark limitiert. Wir haben zwar die Zeichen '0' für 0, '1' für 1, '2' für 2, ... '9' für 9, aber die reichen gerade mal, um Basen <= 10 sinnvoll darzustellen. Man hat dann halt eine Konvention ausgemacht, dass man noch 'A' für 10, 'B' für 11, ... und 'F' für 15 verwendet, weil Basis 16 sehr weit verbreitet ist.
    Aber wie macht man weiter? 'R' für 27? Und was, wenn man über 35 hinaus will?
    '0' bis '9' für 0 bis 9
    'A' bis 'Z' für 10 bis 35
    Und dannn vielleicht noch 'a' bis 'z' für 36 bis 61
    Bei Base64 wurde noch '+' für 62 und '/' für 63 abgemacht, aber dann wird's schon kompliziert.
    Was, wenn man noch weiter will? 5014125?

    Also Strings sind für allgemeines Umrechnen zwischen Zahlensystemen ungeeignet.

    Ich würde da eher folgendes System vorschlagen (nur ein grober Entwurf):

    VB.NET-Quellcode

    1. Class Digit
    2. Value As Integer
    3. End Class
    4. Class Number
    5. Base As Integer
    6. Digits As List(Of Digit)
    7. End Class

    Digit stellt eine einzelne Ziffer dar. Also anstelle eines Chars, das einen Wert repräsentiert ('4' für 4, 'R' für 27) hast Du die Werte direkt:

    VB.NET-Quellcode

    1. Dim Digit1 As New Digit(4)
    2. Dim Digit2 As New Digit(27)

    Number repräsentiert eine Folge von Ziffern hintereinander. Und die Zahl muss auch wissen, welche Basis gemeint ist.
    Als Beispiel: nochmal die Zahl 13 (sagen wir mal der erste Parameter des Konstruktors ist die Basis und der zweite ist eine Auflistung von Ziffern).

    VB.NET-Quellcode

    1. Dim ThirteenBase2 As New Number(2, {New Digit(1), New Digit(1), New Digit(0), New Digit(1)})
    2. Dim ThirteenBase10 As New Number(10, {New Digit(1), New Number(3)})
    3. Dim ThirteenBase16 As New Number(16, {New Digit(13)})


    Jetzt von einer Number-Instanz z.B. einen Integer zu bekommen, ist einfach. Du musst nur folgendes wissen:
    Die Repräsentation "10" in Basis n hat den Wert n.
    Beispiele: "10" in Basis 10 hat den Wert 10. "10" in basis 2 hat den Wert 2. "10" in Basis 16 hat den Wert 16. Und so weiter.
    Du musst die Ziffern also von rechts nach links durchgehen, jede Ziffer mit dem Stellenwert ( = Basis ^ Position) multiplizieren, und das alles zusammenzählen.
    Beispiel:

    VB.NET-Quellcode

    1. Class Number
    2. '...
    3. Public Function ToInt32() As Integer
    4. Dim Sum As Integer = 0
    5. Dim DigitValue As Integer = 1
    6. 'Ziffern von rechts nach links durchlaufen.
    7. For i = Digits.Count - 1 To 0 Step -1
    8. Sum += Digits(i).Value * DigitValue
    9. DigitValue *= Base
    10. Next
    11. Return Sum
    12. End Function
    13. End Class


    Wie Du aber Number und Digit aufbaust, bleibt Dir überlassen, denn ich weiß nicht, wie Du die Zahlen repräsentierst.
    Du musst halt herausfinden, wie Du an die Basis kommst und welche Werte die Digit-Instanzen bekommen.

    Edit: Inzwischen wurde einiges gepostet.
    Negative Zahlen zu behandeln ist auch keine Hexerei. Ich würde hier vorschlagen, die Number-Klasse um einen Boolean IsNegative zu erweitern:

    VB.NET-Quellcode

    1. Class Number
    2. Base As Integer
    3. IsNegative As Boolean
    4. Digits As List(Of Digit)
    5. Function ToInt32() As Integer
    6. End Class

    In der ToInt32-Funktion müsste man nur prüfen, ob IsNegative true ist und entsprechend den wert umdrehen:

    VB.NET-Quellcode

    1. Public Function ToInt32() As Integer
    2. '...
    3. 'Sum enthält immer den absoluten Betrag.
    4. If IsNegative Then
    5. 'Wenn die Zahl negativsein soll, muss einfach nur das Negativ von Sum genommen werden.
    6. Return -Sum
    7. Else
    8. 'Ansonsten einfach nur Sum verwenden, weil positiv.
    9. Return Sum
    10. End If
    11. End Function
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Niko Ortner“ ()

    Leo 97 schrieb:

    bloß mit negativen Zahlen halt noch nicht hinbekommen.

    VB.NET-Quellcode

    1. Dim flag = False
    2. If Value < 0 Then
    3. flag = True
    4. Value = -Value
    5. End If
    6. Dim txt = Convert(Value)
    7. If flag Then
    8. txt = "-" & txt
    9. End If
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo RodFromGermany,

    VB.NET-Quellcode

    1. Dim flag = False
    2. If Value < 0 Then
    3. flag = True
    4. Value = -Value
    5. End If
    6. Dim txt = Convert(Value)
    7. If flag Then
    8. txt = "-" & txt
    9. End If


    Aber das kann ja nicht ganz richtig sein da -4 im Dezimalsystem zum Hexadezimalsystem ja FFFF FFFF FFFF FFFC ist.
    Es gibt keine negativen Zahlen in Zahlensystemen mit Basis ungleich zehn.

    Leo 97 schrieb:

    ungleich zehn
    Da bist Du aber sehr festgelegt.
    Bei mir kann -4Dez auch -4Hex sein, das ist eine Definitionsfrage.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Du vermischst Datentypen und Zahlensysteme.
    -4 ist -4
    -4 ist in Basis 10 "-4"
    -4 ist in Basis 2 "-100"

    Natürlich gibt es auch negative Zahlen in anderen Zahlensystemen. Es gibt auch Kommazahlen in anderen Zahlensystemen: "1101.011" ist die Repräsentation von 13.375 in Basis 2

    Aber:
    -4 ist, ausgehend von Deinem Beispiel, ein Int64. Und dieser Datentyp besagt, dass negative Zahlen als 2's compliment der entsprechenden positiven Zahlen repräsentiert werden.
    4 ist 00000 .... 000100 (das sind 64 Bits, wobei hier eine 0 ein ungesetztes und 1 ein gesetztes Bit darstellt)
    2's compliment: -a = !a + 1
    Also !4 ist 111111 .... 1111011
    Und dann noch + 1 ist 11111 .... 11111100

    Was du machst, ist diese Liste an 64 Bits als Repräsentation einer (positiven) Zahl in Basis 2 zu interpretieren. Und man davon den Wert berechnet und den in Basis 16 darstellt, kommt natürlich "FFF .... FFFC" heraus.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Jo, die machen das halt einfach so. Das ändert aber nichts an der Tatsache, dass -123 in Basis 16 immmer noch "-7B" ist, und nicht "FF85". "FF85" ist nur die Basis 16 Repräsentation vom Wert, den das Bitmuster 1111111110000101 ergibt, wenn man es als Basis 2 Repräsentation interpretiert. Aber das Bitmuster 1111111110000101, wenn es als Int16 betrachtet wird, ist nunmal -123, und nicht 65413. "FF85" ist nämlich die Basis 16 Repräsentation von 65413. Das würde auch herauskommen, wenn man das Bitmuster als UInt16 betrachtet. Es ist nur Zufall, dass Int16 genommen wurde. Ich hätte auch Int32 nehmen können. Dann würden links noch 4 'F's stehen.
    -123 wäre nach Deiner Interpretation das alles: "85", "FF85", "FFFFFF85", "FFFFFFFFFFFFFF85".
    Du kannst beliebig viele 'F's links dran hängen und es wäre trotzdem der gleiche Wert. Aber "85", was ja eigentlich "0085" wäre, und "FF85" sind nicht als gleich zu betrachten. Das eine ist 133 und das andere 65413. Wie genau die Bits interpretiert werden müssen, besagt der Datentyp.
    Beachte auch: Umrechnung zwischen Zahlensystemen funktioniert ja nicht nur bei Computern, sondern generell in der Mathematik. Und da gibt's keine Datentypen. Da würde man bei -123 auch nie auf das Bitmuster 1111111110000101 kommen, sondern man würde auf das kommen: -1111011 mit einer tiefgestellten 2, was andeutet, dass für diese Zahl Basis 2 gilt.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils