Martok - Do 19.10.06 18:15
Titel: Zahlen aus Basis 255 in string
Hallo,
ich hab mal aus Spaß eine HugeNum-Klasse gebastelt. Ja, ich weiß, nix wirklich neues.. ich hab halt grad nix besseres zu tun. Außerdem, man könnte ja was lernen...
Die Daten werden in einem array aus Ziffern der Basis 255 gehalten. Sie kann Nachkommastellen(Fixkomma) und Umwandeln in/aus 'Standard'-Datentypen von Delphi(Int64,Double). Soweit, so gut, aber mit der Umwandlung in/aus String komm ich nicht klar.
Man muss doch aus der Basis 255 erstmal 10 machen, und daraus dann Zeichen, richtig?
Nur: wie mach ich das? Irgendwie komm ich mit den Überträgen nicht klar. Es kommt immer nur Quatsch raus....
Ich häng mal die Unit an. Falls das mal was weltbewegendes wird, kann ich sie ja hier mal 'richtig' veröffentlichen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151:
| unit DUHugeNumber;
interface
uses SysUtils,Math;
const hnBase = high(byte);
type TBase255 = array of byte;
THugeNumber = class IntPart, FracPart:TBase255; Sign:TValueSign; private function GetInt64: Int64; procedure SetInt64(const Value: Int64); function GetDouble: Double; procedure SetDouble(const Value: Double); function GetString: string; procedure SetString(const Value: string); public constructor Create; destructor Destroy; override; property AsInt64:Int64 read GetInt64 Write SetInt64; property AsDouble:Double read GetDouble write SetDouble; property AsString:string read GetString write SetString; end;
function HugeNumberNew:THugeNumber;
implementation
const Epsilon = 1E-15 * 1000;
function HugeNumberNew:THugeNumber; begin Result:= THugeNumber.Create; end;
function Power(Base,Exp:integer):double; begin Result:= Math.IntPower(Base,Exp); end;
function IntPower(Base:integer; Exp:Cardinal):integer; begin Result:= trunc(Math.IntPower(Base,Exp)); end;
constructor THugeNumber.Create; begin inherited; SetLength(IntPart,0); SetLength(FracPart,0); Sign:= +1; end;
destructor THugeNumber.Destroy; begin SetLength(IntPart,0); SetLength(FracPart,0); inherited; end;
function THugeNumber.GetInt64: Int64; var i:integer; begin Result:= 0; for i:= 0 to high(IntPart) do inc(Result,IntPart[i]*IntPower(hnBase,i)); Result:= Result*Sign; end;
procedure THugeNumber.SetInt64(const Value: Int64); var v:int64; i:integer; begin SetLength(FracPart,0); Sign:= Math.Sign(Value); v:= value*Sign; i:= 0; while v>0 do begin SetLength(IntPart,i+1); IntPart[i]:= v mod hnBase; v:=v div hnBase; inc(i); end; end;
function THugeNumber.GetDouble: Double; var i:integer; begin Result:= 0; for i:= 0 to high(IntPart) do Result:= Result+IntPart[i]*IntPower(hnBase,i); for i:= 0 to high(FracPart) do Result:= Result+FracPart[i]*Power(hnBase,-(i+1)); Result:= Result*Sign; end;
procedure THugeNumber.SetDouble(const Value: Double); var v,f:double; i:integer; begin Sign:= Math.Sign(Value); v:= value*Sign; f:= frac(V); SetInt64(Trunc(v));
i:= 0; while (f>epsilon) and (i<15) do begin SetLength(FracPart,i+1); f:= f*hnBase; FracPart[i]:= trunc(f); f:= f-FracPart[i]; inc(i); end; end;
function THugeNumber.GetString: string; Var X: Integer; carry,p:byte; begin Result:= ''; Carry:= 0; For X := 0 To High(IntPart) Do begin end; end;
procedure THugeNumber.SetString(const Value: string); var p,i:integer; begin p:= pos('.',Value); if p<0 then p:= pos(',',Value); if p<0 then p:= length(Value); for i:= p downto 1 do begin end; end;
end. |
Was ich weiß, ist, dass die SetLength-Aufrufe in den Schleifen Müll sind. Die kommen auch noch weg, aber der Einfachheit halber sind sie noch drin.
Grüße,
Sebastian
Horst_H - Fr 20.10.06 07:59
Hallo,
also prinzipiell:
aus
http://rcswww.urz.tu-dresden.de/~s8084100/stuff/Inf1/17Okt03.pdf
...
Umwandlung aus Darstellung mit Ausgangsbasis in Darstellung mit
Zielbasis
Zwei Varianten m¨oglich:
1. Jede Stelle der Zahl mit dem Stellenwert in Zieldarstellung multiplizieren.
Beispiele:
– bin ! dez: 100112 = 1 24 +1 21 +1 20 = 16+2+1 = 19
– dez ! hex: 32710 = 364H+2AH+7 = 12CH+14H+7 =
147H
– dez ! oct: 32710 = 3144O+212O+7 = 454O+24O+7O =
507O
2. Zweite M¨oglichkeit:
(a) Zahl durch Zielbasis dividieren
(b) Rest ist niederwertigste Stelle des Ergebnisses
(c) Quotienten wieder durch Zielbasis dividieren
(d) Rest ist n¨achste Stelle des Ergebnisses
(e) Solange bis c fortsetzen bis Quotient = 0
.....
Ich benutze die erste Variante, indem ich parallel den Stellenwert im Zielsystem erzeuge.
Delphi-Quelltext
1: 2: 3:
| if (Bas1 AND Vergleich)<>0 then ADD_Feld(Summ1Feld^,Summ2Feld^,Feld2_Index,Bas2) |
Statt multiplizeren nutze ich addieren und schieben, da ich so immer leicht in der Zielbasis bleibe.
grosse Zahl als String:
Z='1234567890123456789012345678901234567890.1234567890123456789012345678901234567890'
Z aufteilen in Vorkomma Vz und Nachkommaanteil Nz.
Vorkommaanteil in eine verarbeitbare Basis, die der Komputer schon selbst umwandeln kann (StrToInt)
Also eine 1o-er Potenz von p=1 bis 8. Eine grosse Basis wird sehr viel schneller von meinem Progeramm verarbeitet wie in dem Beitrag zu lesen.
Also aus dem String Vz von hinten nach vorne in Gruppen der Laenge p zerteilen, eventuell führende Nullen ergänzen.
Bei Basis 10 ist p = 1 und jede Ziffer waere in einem Byte von ZahlBasis10 zu speichern.
Diese kann man jetzt durch
BasKonv(10,256,ZahlBasis10,ZahlBasis256);
in die Basis 256 umwandeln.
Die Nachkommastellen umzuwandeln ist doch eine schöne Aufgabe...(Wie geht denn dass???? Basis1Zahl multiplizieren mit Basis2 und die Stellen vor dem Komma abtrennen,umwandeln nach Basis2 und eintragen... )
Gruss Horst