Seite 1 von 1
Ganzzahlenkette "umformen" bzw. komprimieren...
Verfasst: 09.10.2014 19:53
von Ractur
Hallo,
ich suche einen Lösungsansatz wie man eine Ganzzahlenkette komprimieren kann diese aber noch "lesbar" bleibt und mit der Tastatur eingegeben werden kann.
Angenommen ich habe eine Ganzzahlenkette von 20 Ziffern (Immer die gleiche Länge) mit x-beliebiger Reihenfolge der Zahlen
unkomprimierte_kette = 12345678901234567890
und möchte diese nun komprimieren aber natürlich auch wieder dekomprimieren... Zum komprimieren können alle Zeichen der Tastatur verwendet werden, vorzüglich ABC und Zahlen oder nur Zahlen.
Könnte ich nun aus 12345678901234567890 z.B. komprimierte_kette = A2fs7d6213 machen
um nachher wieder aus komprimierte_kette = A2fs7d6213 die unkomprimierte_kette = 12345678901234567890 zu erzeugen?
Womöglich ist dies aber gar nicht möglich?
Danke und Gruß Matthias
Verfasst: 09.10.2014 20:10
von CodeCommander
~ DELETE ~
Re: Ganzzahlenkette "umformen" bzw. komprimieren...
Verfasst: 09.10.2014 20:26
von STARGÅTE
Dafür kannst du Base64 nutzen.
Eine Zahl mit nur Zahlen kann nicht komprimiert werden, wenn weiterhin nur Zahlen erlaubt sind.
Was du nun machen kannst ist zB immer zwei Ziffern in ein Zeichen umzuwandeln, dann brauchst du jedoch 100 verschiedene Zeichen, und somit leider auch Sonderzeichen.
Was auch geht ist immer drei Ziffern in zwei Zeichen wanden, dann bachst du ~32 verschiedene Zeichen.
Oder du nimmst einfach Hex() und Val()
Code: Alles auswählen
Debug "12345678901234567890"
Debug Hex(Val("12345678901234567890"))
Debug StrU(Val("$"+Hex(Val("12345678901234567890"))))
geht allerdings nur bei 2^64-1
Re: Ganzzahlenkette "umformen" bzw. komprimieren...
Verfasst: 09.10.2014 21:33
von NicTheQuick
Ich hatte da mal was gemacht, was Zahlen von einem Zahlensystem in ein anderes übersetzen kann. Wenn man eine Dezimalzahl übersetzt in das 36er-System, dann wird sie auch kürzer.
Code: Alles auswählen
Procedure.s Base_Convert(Value.s, InBase.l = 10, OutBase.l = 2, nbDecimals.l = 100)
Protected p.l, *c.Character, left.s, l.l, lout.s, Mod.l, out.s, rout.s, right.s, a.l
*c = @Value
While *c\c
Select *c\c
Case '0' To '9' : *c\c - '0' + 1
Case 'a' To 'z' : *c\c - 'a' + 11
Case 'A' To 'Z' : *c\c - 'A' + 11
Case '.' ;do nothing
Default : *c\c = 1
EndSelect
*c + SizeOf(Character)
Wend
p = FindString(Value, ".", 1)
If p
left = Left(Value, p - 1)
right = Mid(Value, p + 1, Len(Value) - p)
Else
p = Len(Value)
left = Value
right = ""
EndIf
If left ;Vorkommateil
While left <> ""
Mod = 0 : *c = @left : out = ""
While *c\c
Mod = Mod * InBase + *c\c - 1
l = Mod / OutBase
If l Or out
out + Chr(l + 1)
EndIf
Mod - (l * OutBase)
*c + SizeOf(Character)
Wend
left = out
lout = Chr(Mod + 1) + lout
Wend
Else
lout = Chr(1)
EndIf
If right ;Nachkommateil
a = 0
p = Len(right)
While right <> Chr(1) And a < nbDecimals
*c = @right + (p - 1) * SizeOf(Character)
p = 0 : Mod = 0 : out = ""
While *c >= @right
Mod + (*c\c - 1) * OutBase
out = Chr((Mod % InBase) + 1) + out
Mod / InBase
*c - SizeOf(Character)
p + 1
Wend
right = out
rout + Chr(Mod + 1)
a + 1
Wend
EndIf
If rout : out = lout + "." + rout : Else : out = lout : EndIf
*c = @out
While *c\c
Select *c\c
Case 1 To 10 : *c\c + '0' - 1
Case 11 To 36 : *c\c + 'A' - 11
Case '.' ;do nothing
Default : *c\c = '?'
EndSelect
*c + SizeOf(Character)
Wend
ProcedureReturn out
EndProcedure
Define unkomprimiert.s = "12345678901234567890"
Define komprimiert.s = Base_Convert(unkomprimiert, 10, 36, 100)
Define dekomprimiert.s = Base_Convert(komprimiert, 36, 10, 100)
Debug "Unkomprimiert: " + unkomprimiert
Debug "Komprimiert: " + komprimiert
Debug "Dekomprimiert: " + dekomprimiert
Jetzt könnte man den Code natürlich noch umbauen, sodass mehr als 36 verschiedene Zeichen gehen.
Übrigens kommt der Code auch mit beliebig langen Dezimalzahlen zurecht.
Re: Ganzzahlenkette "umformen" bzw. komprimieren...
Verfasst: 09.10.2014 21:50
von NicTheQuick
Noch schnell eine weitere Version. Diese geht bis zum 62er-System. Das heißt jede Ziffer kann 0-9, A-Z oder a-z sein.
Aus deiner 20-stelligen Zahl wird so eine 11-stellige.
Code: Alles auswählen
Procedure.s Base_Convert(Value.s, InBase.l = 10, OutBase.l = 2, nbDecimals.l = 100)
Protected p.l, *c.Character, left.s, l.l, lout.s, Mod.l, out.s, rout.s, right.s, a.l
*c = @Value
While *c\c
Select *c\c
Case '0' To '9' : *c\c - '0' + 1
Case 'A' To 'Z' : *c\c - 'A' + 11
Case 'a' To 'z' : *c\c - 'a' + 11 + Bool(InBase > 36) * 26
Case '.' ;do nothing
Default : *c\c = 1
EndSelect
*c + SizeOf(Character)
Wend
p = FindString(Value, ".", 1)
If p
left = Left(Value, p - 1)
right = Mid(Value, p + 1, Len(Value) - p)
Else
p = Len(Value)
left = Value
right = ""
EndIf
If left ;Vorkommateil
While left <> ""
Mod = 0 : *c = @left : out = ""
While *c\c
Mod = Mod * InBase + *c\c - 1
l = Mod / OutBase
If l Or out
out + Chr(l + 1)
EndIf
Mod - (l * OutBase)
*c + SizeOf(Character)
Wend
left = out
lout = Chr(Mod + 1) + lout
Wend
Else
lout = Chr(1)
EndIf
If right ;Nachkommateil
a = 0
p = Len(right)
While right <> Chr(1) And a < nbDecimals
*c = @right + (p - 1) * SizeOf(Character)
p = 0 : Mod = 0 : out = ""
While *c >= @right
Mod + (*c\c - 1) * OutBase
out = Chr((Mod % InBase) + 1) + out
Mod / InBase
*c - SizeOf(Character)
p + 1
Wend
right = out
rout + Chr(Mod + 1)
a + 1
Wend
EndIf
If rout : out = lout + "." + rout : Else : out = lout : EndIf
*c = @out
While *c\c
Select *c\c
Case 1 To 10 : *c\c + '0' - 1
Case 11 To 36 : *c\c + 'A' - 11
Case 37 To 62 : *c\c + 'a' - 37
Case '.' ;do nothing
Default : *c\c = '?'
EndSelect
*c + SizeOf(Character)
Wend
ProcedureReturn out
EndProcedure
Define unkomprimiert.s = "12345678901234567890"
Define komprimiert.s = Base_Convert(unkomprimiert, 10, 62, 100)
Define dekomprimiert.s = Base_Convert(komprimiert, 62, 10, 100)