hex, dezimal

Für allgemeine Fragen zur Programmierung mit PureBasic.
hth
Beiträge: 76
Registriert: 08.10.2004 22:47

hex, dezimal

Beitrag von hth »

x=255
x$=Hex(x) ;dezimal zu hexadezimal


Wie komme ich ohne größeren Aufwand in die Gegenrichtung?
Oder muss ich mir dafür wirklich eine eigene Funktion (Procedure) schreiben?
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

Speziell von PureBasic aus gibt es keinen Befehl der einen Hex-String wieder in eine Dezimalvariable wandelt. Also wenn du von "FF" (dem Hex-Wert) wieder auf 255 kommen willst, musst du dir da einen Algorithmus schreiben welcher dies umrechnet.

Ich hab dazu hier mal schnell eine Prozedur geschrieben:

Code: Alles auswählen

Procedure hex_2_dec(hex$)

  Protected decimal_wert
  decimal_wert = 0
  
  For z = 0 To Len(hex$) - 1
    hex_single$ = Mid(hex$, Len(hex$) - z, 1)
    Select hex_single$
      Case "0"
        decimal_wert = decimal_wert + (0 * Pow(16, z))
      Case "1"
        decimal_wert = decimal_wert + (1 * Pow(16, z))
      Case "2"
        decimal_wert = decimal_wert + (2 * Pow(16, z))
      Case "3"
        decimal_wert = decimal_wert + (3 * Pow(16, z))
      Case "4"
        decimal_wert = decimal_wert + (4 * Pow(16, z))
      Case "5"
        decimal_wert = decimal_wert + (5 * Pow(16, z))
      Case "6"
        decimal_wert = decimal_wert + (6 * Pow(16, z))
      Case "7"
        decimal_wert = decimal_wert + (7 * Pow(16, z))
      Case "8"
        decimal_wert = decimal_wert + (8 * Pow(16, z))
      Case "9"
        decimal_wert = decimal_wert + (9 * Pow(16, z))
      Case "A"
        decimal_wert = decimal_wert + (10 * Pow(16, z))
      Case "B"
        decimal_wert = decimal_wert + (11 * Pow(16, z))
      Case "C"
        decimal_wert = decimal_wert + (12 * Pow(16, z))
      Case "D"
        decimal_wert = decimal_wert + (13 * Pow(16, z))
      Case "E"
        decimal_wert = decimal_wert + (14 * Pow(16, z))      
      Case "F"
        decimal_wert = decimal_wert + (15 * Pow(16, z))
    EndSelect
  Next z

  ProcedureReturn decimal_wert
EndProcedure

Debug hex_2_dec("FF")
Jetzt kannst du einen beliebig langen Hex-String eingeben und erhälst dazu den Dezimalwert. Ich habs jetzt explizit mit 2-Stellen getestet, sollte aber auch mit 3, 4, 5, oder mehr Stellen gehen. ;)

Dabei arbeitet die Prozedur so, dass sie von rechts nach links die Stellen abliest und sie den Dezimalwerten zuordnet und ausrechnet. Ganz rechts angefangen würde das bei "F" also 15 * 16^0 = 15 sein.
Diesen Wert + den nächsten, nämlich 15 * 16^1 = 240 + 15 = 255 = "FF"
Wie du ja sicher weißt beginnt man da rechts und bei dem Exponenten 0 und arbeitet sich Stellenweise nach links vor, jeweils um 1 erhöhen. Meine Prozedur arbeitet dabei dynamisch, egal wie viele Stellen man hat, mittels For-Schleife und geht somit alle Stellen ab.
Jetzt könnte man vielleicht noch eine Fehlerroutine-Prüfung einbauen die erstmal abfragt, ob der eingegebene String wirklich ein Hex-Wert ist. Aber davon geh ich mal aus, dass du es dafür nutzt. Kannst du ja noch erweitern. ;)
hth
Beiträge: 76
Registriert: 08.10.2004 22:47

hex_dec

Beitrag von hth »

Danke für deine Antwort,

ich hatte auch schon so was ähnliches. Dachte aber, dass es doch noch
eine versteckte spezielle Funktion gibt.

Code: Alles auswählen

Procedure.l hex_dec(x$)
  
  x$=UCase(x$)
  l=Len(x$)
  
  For i=1 To l
        
      h1$=Mid(x$,i,1)      
      h1=Val(h1$)
            
      Select h1$      
          Case "A"
              h1=10
          Case "B"
              h1=11
          Case "C"
              h1=12
          Case "D"
              h1=13
          Case "E"
              h1=14
          Case "F"
              h1=15     
      EndSelect      
      
      h1=h1*Pow(16,l-i)      
                    
      x=x+h1      
   
   Next i

  ProcedureReturn x
EndProcedure


Debug hex_dec("FF")

Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Hier mal noch ein paar andere (kleine) Versionen:

Code: Alles auswählen

; Autor: ?
; Datum: ?
; Forum: ?
Procedure.l hex2dec(h$)
  h$=UCase(h$)
  For r=1 To Len(h$)
    d<<4 : a$=Mid(h$,r,1)
    If Asc(a$)>60
      d+Asc(a$)-55
    Else
      d+Asc(a$)-48
    EndIf
  Next
  ProcedureReturn d
EndProcedure
;
Debug hex2dec("FF")
Debug hex2dec("FFFF")
Debug hex2dec("FFFFFF")
Debug StrU(hex2dec("FFFFFFFF"),#LONG)
Oder mit Pointer:

Code: Alles auswählen

;
; by Danilo, 15.01.2004 - german chat (for Suco-X)
;
; 22.07.2004  -  changed to pointers by Danilo
;
Procedure Hex2Dec(String$)
  *String.BYTE = @String$
  If *String
    If *String\b = '$'   : *String + 1 : EndIf
    
    num = *String\b
    While num
      result << 4
      If     num >= '0' And num <= '9'  ; 0 - 9
        result + num - '0'
      ElseIf num >= 'A' And num <= 'F'  ; A - F
        result + num - 55 ; 'A' + 10
      ElseIf num >= 'a' And num <= 'f'  ; a - f
        result + num - 87 ; 'a' + 10
      Else
        ProcedureReturn 0               ; Error: not 0-9,A-F,a-f
      EndIf
      *String+1
      num = *String\b
    Wend
  EndIf
  ProcedureReturn result
EndProcedure

Debug Hex2Dec("")
Debug Hex2Dec("$c")
Debug Hex2Dec("$FA")
Debug Hex2Dec("$FFFF")
Debug Hex2Dec("$7FFFFFFF")
Debug Hex2Dec("$FFFFFFFF")
Debug StrU(Hex2Dec("$FFFFFFFF"),#LONG)
Und hier gleich noch ein paar andere Prozeduren von
F. Weil hinterher:

Code: Alles auswählen

;It's a bit long but may it help some of us ...
;
;I tested as much as possible To have good performances And bugless results.
;
;I suppose it exist a better solution using assembly but I do Not have so much time To find ...
;
;**************************************
Dim Dec2BaseDigit.s(16)

Dec2BaseDigit(0) = "0"
Dec2BaseDigit(1) = "1"
Dec2BaseDigit(2) = "2"
Dec2BaseDigit(3) = "3"
Dec2BaseDigit(4) = "4"
Dec2BaseDigit(5) = "5"
Dec2BaseDigit(6) = "6"
Dec2BaseDigit(7) = "7"
Dec2BaseDigit(8) = "8"
Dec2BaseDigit(9) = "9"
Dec2BaseDigit(10) = "A"
Dec2BaseDigit(11) = "B"
Dec2BaseDigit(12) = "C"
Dec2BaseDigit(13) = "D"
Dec2BaseDigit(14) = "E"
Dec2BaseDigit(15) = "F"

Global Dec2BaseDigit

Procedure.s Dec2Base(n.l, Base.l)
  RB.l
  Out.s = ""
  Select Base
    Case 16
      Out = Hex(n)
    Default
      Result.l = n
      Res.l = 0
      While Result > 0
        RB = Result / Base
        Res = Base * RB
        Out = Dec2BaseDigit(Result - Res) + Out
        Result = RB
      Wend
      If Out = ""
          Out = "0"
      EndIf
  EndSelect
  ProcedureReturn Out
EndProcedure

Procedure.s Dec2Hex(n.l)
  Res.l
  R16.l
  Result.l = n
  Out.s = ""
  While Result > 0
    R16 = Result >> 4
    Res = R16 << 4
    Out = Dec2BaseDigit(Result - Res) + Out
    Result = R16
  Wend
  If Out = ""
      Out = "0"
  EndIf
  ProcedureReturn Out
EndProcedure

Procedure.s Dec2Oct(n.l)
  Res.l
  R8.l
  Result.l = n
  Out.s = ""
  While Result > 0
    R8 = Result >> 3
    Res = R8 << 3
    Out = Dec2BaseDigit(Result - Res) + Out
    Result = R8
  Wend
  If Out = ""
      Out = "0"
  EndIf
  ProcedureReturn Out
EndProcedure

Procedure.s Dec2Bin(n.l)
  Res.l
  R2.l
  Result.l = n
  Out.s = ""
  While Result > 0
    R2 = Result >> 1
    Res = 2 * R2
    Out = Dec2BaseDigit(Result - Res) + Out
    Result = R2
  Wend
  If Out = ""
      Out = "0"
  EndIf
  ProcedureReturn Out
EndProcedure

Procedure Bin2Dec(n.s)
Result.l
  For i = 1 To Len(n)
    Result = 2 * Result + Val(Mid(n, i, 1))
  Next
  ProcedureReturn Result
EndProcedure

Procedure Oct2Dec(n.s)
Result.l
  For i = 1 To Len(n)
    Result = 8 * Result + Val(Mid(n, i, 1))
  Next
  ProcedureReturn Result
EndProcedure

Procedure Hex2Dec(n.s)
Result.l
Digit.l
  For i = 1 To Len(n)
    Select Mid(n, i, 1)
      Case "A"
        Digit = 10
      Case "B"
        Digit = 11
      Case "C"
        Digit = 12
      Case "D"
        Digit = 13
      Case "E"
        Digit = 14
      Case "F"
        Digit = 15
      Default
        Digit = Val(Mid(n, i, 1))
    EndSelect
    Result = 16 * Result + Digit
  Next
  ProcedureReturn Result
EndProcedure

;
; Main starts here for testing
;  

DecConst.l
BinConst.s
OctConst.s
HexConst.s

OpenConsole()

DecConst = 16434824
BinConst = "111110101100011010001000"
OctConst = "76543210"
HexConst = "FAC688"

PrintN("Dec2Base(n,2)   : Dec2Base(" + Str(DecConst) + ",2) =" + Dec2Base(DecConst, 2))
PrintN("Dec2Bin(n)      : Dec2Bin(" + Str(DecConst) + ")    =" + Dec2Bin(DecConst))
PrintN("Dec2Base(n,8)   : Dec2Base(" + Str(DecConst) + ",8) =" + Dec2Base(DecConst, 8))
PrintN("Dec2Oct(n)      : Dec2Oct(" + Str(DecConst) + ")    =" + Dec2Oct(DecConst))
PrintN("Dec2Base(n,16)  : Dec2Base(" + Str(DecConst) + ",16)=" + Dec2Base(DecConst, 16))
PrintN("Dec2Hex(n)      : Dec2Hex(" + Str(DecConst) + ")    =" + Dec2Hex(DecConst))
PrintN("Hex(n)          : Hex(" + Str(DecConst) + ")        =" + Hex(DecConst))
PrintN("Bin2Dec(n)      : Bin2Dec(" + BinConst + ")         =" + Str(Bin2Dec(BinConst)))
PrintN("Oct2Dec(n)      : Oct2Dec(" + OctConst + ")         =" + Str(Oct2Dec(OctConst)))
PrintN("Hex2Dec(n)      : Hex2Dec(" + HexConst + ")         =" + Str(Hex2Dec(HexConst)))

;
; and for fun ...
;

PrintN(Str(Hex2Dec(Dec2Hex(123456789))))
PrintN(Str(Oct2Dec(Dec2Oct(123456789))))
PrintN(Str(Bin2Dec(Dec2Bin(123456789))))

While Inkey() = ""
Wend

CloseConsole()

End
;**************************************

;Francois Weil
;14, rue Douer
;F64100 Bayonne
Sollte Fred vielleicht wirklich mal direkt einbauen, falls er mal
ein paar Minuten Zeit hat... ist auf jeden Fall nützlich und wird
von vielen Leuten gebraucht - so wie Asc, Val und ValF.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Andre
PureBasic Team
Beiträge: 1735
Registriert: 11.09.2004 16:35
Computerausstattung: MacBook Core2Duo mit MacOS 10.6.8
Lenovo Y50 i7 mit Windows 8.1
Wohnort: Saxony / Deutscheinsiedel
Kontaktdaten:

Beitrag von Andre »

Sollte Fred vielleicht wirklich mal direkt einbauen, falls er mal
ein paar Minuten Zeit hat... ist auf jeden Fall nützlich und wird
von vielen Leuten gebraucht - so wie Asc, Val und ValF.
Habe daher diesen Wunsch auch mitsamt Beispielen an Fred weitergeleitet.
Bye,
...André
(PureBasicTeam::Docs - PureArea.net | Bestellen:: PureBasic | PureVisionXP)
hth
Beiträge: 76
Registriert: 08.10.2004 22:47

Noch eine Lösung, die mir im Traum eingefallen ist.

Beitrag von hth »

Code: Alles auswählen

Procedure.l hex_dec(x$)

  x$=lCase(x$)
  l=Len(x$)
  
  For i=1 To l
        
      h1$=Mid(x$,i,1)  
          
      n=FindString("0123456789abcdef",h1$,1)           
                    
      x=x+(n-1)*Pow(16,l-i)      
   
  Next i

  ProcedureReturn x
EndProcedure


Debug hex_dec("FF")
Benutzeravatar
Sylvia
verheiratet<br>1. PureGolf-Gewinner
Beiträge: 487
Registriert: 29.08.2004 09:42
Wohnort: Old Europe

Beitrag von Sylvia »

Na, dann will ich mal noch meinen Senf dazugeben...

Code: Alles auswählen

; **********************************
; * 09.Oct.2004 "Sylvia" GermanForum
; **********************************

Procedure Dec(NoDec$)
     ; wandelt einen Hex$ / Bin$ um in einen Dezimalwert.
     ; Die Umwandlung erfolgt bis zum ersten ungültigen Zeichen
     ; "Overflow" wird nicht überprüft (unkritisch)
          
     ; NoDec$ = 1.Zeichen ->$ Wert wird als Hexzahl behandelt
     ;                    ->% Wert wird als Binärzahl behandelt
  
     Protected Result,x,Char
  
     If   PeekB(@NoDec$)='$'    ;Hex -> Dec
               
          NoDec$=UCase(NoDec$)

          x=1: Char=PeekB(@NoDec$+x)
          While Char
               Result << 4
               If     Char='0'
               ElseIf Char='1': Result+ 1
               ElseIf Char='2': Result+ 2
               ElseIf Char='3': Result+ 3
               ElseIf Char='4': Result+ 4
               ElseIf Char='5': Result+ 5
               ElseIf Char='6': Result+ 6
               ElseIf Char='7': Result+ 7
               ElseIf Char='8': Result+ 8
               ElseIf Char='9': Result+ 9
               ElseIf Char='A': Result+10
               ElseIf Char='B': Result+11
               ElseIf Char='C': Result+12
               ElseIf Char='D': Result+13
               ElseIf Char='E': Result+14
               ElseIf Char='F': Result+15
               Else:  ProcedureReturn Result >> 4
               EndIf
          
               x+1: Char=PeekB(@NoDec$+x)
          Wend
               
     ElseIf PeekB(@NoDec$)='%'     ; Bin -> Dec
     
          x=1: Char=PeekB(@NoDec$+x)
          While Char
               Result << 1
               If     Char='0'
               ElseIf Char='1': Result+1
               Else:  ProcedureReturn Result >> 1
               EndIf
                  
               x+1: Char=PeekB(@NoDec$+x)
          Wend

     EndIf
  
     ProcedureReturn Result 
EndProcedure 


Debug dec("$ff")                  ; =255
Debug dec("$7F FF 00")            ; =127 Space is no valid
Debug dec("%1010")                ; = 10
Debug dec("%111F")                ; =  7 'F' is no valid in Binary
Debug dec("$FFCDAFBCDF53A31C90")  ; ok,ok,ok...no problem, cut by 53A31C90 :D
Basic Pur = PureBasic
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8426
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 20.10
NVIDIA Quadro P2200
Wohnort: Saarbrücken
Kontaktdaten:

Beitrag von NicTheQuick »

Hier noch eine schnelle Bin2Dec-Procedure, die nur funktioniert, wenn wirklich nur "0"en und "1"en im String stehen. Sonst schlägt sie fehl.

Code: Alles auswählen

Binaer.s = InputRequester("Binär -> Dezimal", "Geben sie eine Binärzahl ein.", "")

Dezimal = 0
*z.BYTE = @Binaer

While *z\b
  a = *z\b - 48
  
  Dezimal << 1
  Dezimal + a
  
  *z + 1
Wend

MessageRequester("Binär -> Dezimal", "Binärzahl: " + Binaer + #CRLF$ + "Dezimalzahl:" + Str(Dezimal))
Bild
Kaeru Gaman
Beiträge: 17386
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ich würde mir mega-booleans wünschen:

Code: Alles auswählen

i=asc(a$)
a=(48<=i<=57)*(i-48)+(65<=i<=70)*(i-55)
;) ;) ;)
wer verstehts?

geht auch mit einfachen booleans:

Code: Alles auswählen

i=asc(a$)
a=((i>=48)and(i<=57))*(i-48)+((i>=65)and(i<=70))*(i-55)
... machts gut und danke für den fisch ...
Heroglyph
Beiträge: 41
Registriert: 22.11.2004 20:34

Beitrag von Heroglyph »

Kanns mir nicht verkneifen :).

Code: Alles auswählen

Procedure Hex2Dec(N.s)
  For i = 1 To Len(N)
    d = (d << 4) + Asc(UCase(Mid(N,i,1)))-48 - 7 * (Asc(UCase(Mid(N,i,1)))>>6)
  Next
  ProcedureReturn d
EndProcedure


Debug Hex2Dec("FF")
Debug Hex2Dec("F1")
Debug Hex2Dec("CAFEBABE")
Debug Hex2Dec("10000")
Debug Hex2Dec(Hex(-4))
God is real, unless declared integer.
Antworten