Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Eigenen Variablentyp
Frolo - Mo 01.04.13 23:24
Titel: Eigenen Variablentyp
Hey,
mir ist, als ich nach dem Typ TColor folgende Seite aufgefallen:
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Graphics_TColor.html
Da wird der Typ ganz lapidar so definiert:
Delphi-Quelltext
1:
| TColor = -$7FFFFFFF-1..$7FFFFFFF; |
Jetzt kamen mir ein paar Fragen auf:
1. Kann ich jetzt einen Typen TVeryLongInt = -$FFFFFFFFFFFFFFFFFFFFFFF..$FFFFFFFFFFFFFFFFFFFFFFF definieren?
2. Ich hab mir das immer so vorgestellt, dass ich einfach nur die Größe des Typs angebe, also zB. Char = $FF. Ich verstehe das - und .. nicht. Da wird irgendein Zahlenbereich angegeben oder? Nur was macht eine negative Zahl bei TColor für einen Sinn?
3. Warum 7F? Warum nicht einfach FF?
4. Was macht das -1 am Ende des ersten Elements?
Danke für eure Antworten :)
OlafSt - Di 02.04.13 00:07
Zu 1.) Ja, solange sich dein TVeryLongInt in irgendeinen bereits vordefinierten Variablentyp paßt. Der TColor paßt übrigens in einen integer.
Zu 2.) Korrekt erkannt, das ist ein Zahlenbereich. Betrachte die Zahlen mal Binär, dann wird das mit dem $7FFFFFFF schlagartig klar ;)
Zu 3.) Siehe 2a)
Zu 4.) Eins abziehen.
Frolo - Di 02.04.13 10:23
Ja okay, aber mir erschließt sich noch immer nicht, wieso man bei TColor nen negativen wert hat.. o: Vllt wäre es hilfreich, wenn ihr mir bei Integer zB zeigen könntet, wie zB -1 Hexadezimal bzw Binär aussieht :)
Außerdem ist es dann überhaupt möglich einen komplett neuen Zahlentyp mit sagen wir mal 16 Bytes zu "schaffen"?
knittel - Di 02.04.13 11:23
Also du wirst es nicht schaffen können zum Beispiel einen Int128 einzubauen, da dieser nicht in einen bekannten Variablentyp passt (Int64 ist der größte in Delphi).
Um das mit den -1 zu erklären:
Wir nehmen dafür als einfaches Beispiel einfach mal einen ShortInt (selbe größe wie ein Byte)
Der sieht dann binär so aus:
00000000
Dieser besteht aus 8 Bits. Folglich gibt es 2^8 verschiedene Einstellungsmöglichkeiten. Das wären ausgrechnet 256.
Bei einem unsigned Byte (nur positive Zahlen) wäre das 0..255 in Dezimal oder in Hexadezimal $0..$FF.
Da wir aber einen signed Byte haben, haben wir sowohl positive als auch negative Zahlen.
Folglich würde man erst annehmen das es dann folgende Zahlen gibt -127..127 oder in Hexadezimal $-7F..$7F
Wenn wir jetzt aber genau aufpassen, werden wir merken, dass wir nur 255 Möglichkeiten ausnutzen (2 * 127 + 1(Die Null)) obwohl wir 256 haben. Deswegen macht
man bei dem ersten Teil noch ein -1 davor, damit man dann die Zahlen von -128..127 hat.
Intern wird das nämlich meist (eigentlich immer) über einen Bias geregt. Der Bias wäre hier zum Beispiel -128. Daher wäre folgender Wert 01000000 -> umgerechnet 64 -> Bias dazurechnen (64 - 128) -> -64.
FaTaLGuiLLoTiNe - Di 02.04.13 11:42
Frolo hat folgendes geschrieben : |
Ja okay, aber mir erschließt sich noch immer nicht, wieso man bei TColor nen negativen wert hat.. |
Soweit ich weiss ist der negative Wertebereich von TColor für die Windows-Systemfarben reserviert.
Frolo - Di 02.04.13 12:52
Bleiben noch 2 Fragen offen:
die erste wäre:
1. Wie stellt man negative Zahlen in hexadezimaler oder binärer Form da? 1 wäre ja 01 bzw $01 nur was wäre dann -1?
2. Wenn ich jetzt nen Int128 unbedingt bräuchte (ist ja kein Variablentyp vorhanden). Kann ich mir so einen nicht einfach selbst schreiben? Im Endeffekt ist es doch "nur" ein größerer Speicherbereich im Arbeitsspeicher oder?
Blup - Di 02.04.13 13:48
1.)
Wird das erste Zeichen als Vorzeichen betrachtet, wird die Binär ohne Vorzeichen darstellbare größte Zahl zur -1 (alle Bits sind gesetzt):
Quelltext
1: 2: 3: 4:
| Hexadezimal: $80 - $FF, $00 - $7F Binär: 10000000 - 11111111, 00000000 - 01111111 vorzeichenlos Dezimal: 128 - 255, 0 - 127 vorzeichenbehaftete Dez.: -128 - -1, 0 - 127 |
2.)
Der Compiler kennt keine Operationen mit denen er solche Zahlen verarbeiten kann.
Aktuelle Compilerversionen erlauben aber die Definition eigener Operatoren für Records.
Kleines Beispiel zur Summierung sehr langer Zahlen:
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: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169:
| unit BigNum;
interface
type TBigNum = record Count: Integer; Data: array of Longword; class operator Add(v1, v2: TBigNum): TBigNum; class operator Equal(v1, v2: TBigNum): Boolean; class operator Implicit(const v1: TBigNum): AnsiString; class operator Implicit(const v1: AnsiString): TBigNum; procedure Add(const v1: TBigNum); end;
implementation
uses SysUtils;
class operator TBigNum.Implicit(const v1: TBigNum): AnsiString; var n: Integer; p: PByte; pc: PChar; b: Byte; begin n := v1.Count; if n = 0 then Result := '0' else begin p := @(v1.Data[n div 8]); Inc(p, (n mod 8) div 2); SetLength(Result, n); pc := @(Result[1]);
if Odd(n) then begin b := p^; Dec(p); pc^ := Char(b + Ord('0')); Inc(pc); Dec(n); end; while n > 0 do begin b := p^; Dec(p); pc^ := Char((b div 10) + Ord('0')); Inc(pc); pc^ := Char((b mod 10) + Ord('0')); Inc(pc); Dec(n, 2); end; end; end;
class operator TBigNum.Implicit(const v1: AnsiString): TBigNum; var n1, n2, i: Integer; s: AnsiString; b: Byte; pb: PByte; pc: PChar;
function NextCharValue: Byte; begin if n1 <= 0 then Result := 0 else begin Result := Ord(pc^) - Ord('0'); if not (Result in [0..9]) then raise Exception.Create('Ungültige Zeichenfolge'); Dec(pc); Dec(n1); end end;
begin s := Trim(v1); n1 := Length(s); Result.Count := n1; try n2 := (n1 + 7) div 8; if Length(Result.Data) < n2 then SetLength(Result.Data, n2);
pc := @(s[n1]); pb := @(Result.Data[0]); for i := 0 to (n2 * 4) - 1 do begin b := NextCharValue; b := NextCharValue * 10 + b; pb^ := b; Inc(pb); end; except Result.Count := 0; raise; end; end;
procedure TBigNum.Add(const v1: TBigNum);
function GetValue(p: PByte; var n: Integer): Byte; inline; begin if n = 0 then Result := 0 else begin Result := p^; Dec(n); end; end;
var p1, p2: PByte; n1, n2, n, i: Integer; b1, b2, c: Byte; begin n1 := Count; n2 := v1.Count; if n1 > n2 then n := n1 else n := n2; if n > Length(Data) then SetLength(Data, n);
p1 := PByte(Data); p2 := PByte(v1.Data); c := 0; for i := 0 to n - 1 do begin b1 := GetValue(p1, n1); b2 := GetValue(p2, n2); b1 := b1 + b2 + c; c := b1 div 100; b1 := b1 mod 100; p1^ := b1; Inc(p1); Inc(p2); end; if c <> 0 then begin Inc(n); if n > Length(Data) then SetLength(Data, n); Data[n - 1] := c; end; Count := n; end;
class operator TBigNum.Add(v1, v2: TBigNum): TBigNum; begin Result.Data := Copy(v1.Data); Result.Count := v1.Count; Result.Add(v2); end;
class operator TBigNum.Equal(v1, v2: TBigNum): Boolean; begin Result := (v1.Count = v2.Count) and CompareMem(Pointer(v1.Data), Pointer(v2.Data), v1.Count * SizeOf(v1.Data[0])); end; |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| uses BigNum;
var a, b: TBigNum; c: string; begin a := '1234567890123456789012345678901234567890123456789012345678901234567890'; b := '0987654321098765432109876543210987654321098765432109876543210987654321'; c := a + b; writeln(c); end; |
Frolo - Di 02.04.13 20:30
Vielen Dank für die Antworten. Ich hab nur die binäre Darstellung von negativen Zahlen nicht verstanden. Nehmen wir mal ein Byte und sagen es soll von -128 bis 127 gehen (ka ob das unsigned oder so heißt :D ) Wie sehen da zB -128, 0, -1, 1, 127 und 64 oder -64 aus? Ich brauch anscheinend Beispiele.
Bei positiven Werten ist das ja klar: Also Byte (0..255)
0 -> 0000 0000
1 -> 0000 0001
255 -> 1111 1111
Aber bei negativen :D
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!