Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Zwei Werte [0..16] in einem Integer festhalten (https://www.delphipraxis.net/151381-zwei-werte-%5B0-16%5D-einem-integer-festhalten.html)

Jonelmeier 15. Mai 2010 11:34


Zwei Werte [0..16] in einem Integer festhalten
 
Hallo!

Ich habe gerade ein kleines Problem: Und zwar soll ich zwei Werte in einem Integer festhalten.
Die Werte liegen zwischen MIN_X..MAX_X und MIN_Y..MAX_Y (im konkreten Beispiel jeweils zwischen 1 und 16, das soll aber variabel bleiben).
Nun stehe ich total auf dem Schlauch!
Gibt es eine mathematische Lösung für das Problem? Wäre aber auch mit einer Idee für eine Q&D Lösung zufrieden, da ich echt keine Ahnung habe...

Gruß!

Luckie 15. Mai 2010 11:36

Re: Zwei Werte [0..16] in einem Integer festhalten
 
Wie wäre es mit dem Datentyp TPoint?

Jonelmeier 15. Mai 2010 11:40

Re: Zwei Werte [0..16] in einem Integer festhalten
 
Zitat:

Zitat von Luckie
Wie wäre es mit dem Datentyp TPoint?

Ich muss leider einen Integer zum speichern verwenden...das ist ja das Problem...

himitsu 15. Mai 2010 11:41

Re: Zwei Werte [0..16] in einem Integer festhalten
 
Entweder du löst das Mathematisch

Delphi-Quellcode:
// setzen
G := A * 100 + B;

// auslesen
A := G div 100;
B := G mod 100;
oder über einen Record ... analog zu Delphi-Referenz durchsuchenTSmallPoint (TPoint sind 2 Integer in einem Int64)
Delphi-Quellcode:
type
  TSplitt = record
  case Integer of
    0: (g: LongInt);
    1: (a, b: Word);
  end;

// setzen
Splitt.a := A;
Splitt.b := B;
g := Splitt.g;

// auslesen
Splitt.g := G;
A := Splitt.a;
B := Splitt.b;

// auslesen
A := TSplitt(G).a;
B := TSplitt(G).b;
oder
Delphi-Quellcode:
type
  TSplitt = record
  class function Set(A, B: Word): LongInt;
  case Integer of
    0: (g: LongInt);
    1: (a, b: Word);
  end;

class function TSplitt.Set(A, B: Word): LongInt;
begin
  TSplitt(Result).a := A;
  TSplitt(Result).b := B;
end:

// setzen
TSplitt(G).a := A;
TSplitt(G).b := B;

// setzen
G := TSplitt.Set(A, B);

// auslesen
Splitt.g := G;
A := Splitt.a;
B := Splitt.b;

// auslesen
A := TSplitt(G).a;
B := TSplitt(G).b;
Das Ganze kann man notfalls noch in Funktionen kapseln:

Typgrößen und Multiplikatoren können/müssen natürlich noch angepaßt werden.

Meflin 15. Mai 2010 12:00

Re: Zwei Werte [0..16] in einem Integer festhalten
 
Dank der Unendlichkeit der natürlichen Zahlen ist dies tatsächlich einwandfrei mathematisch lösbar, bekannt als Cantorsche Paarungsfunktion (mit der man sogar beliebig viele natürliche Zahlen auf eine einzige umkehrbar abbilden kann).

http://upload.wikimedia.org/math/7/9...63de70c533.png

Beispiel: du willst (5,3) speichern. Das wäre dann einfach ((5 + 3) * (5 + 3 + 1)) / 2 + 3 = 39.

Zur Umkehrung benötigt man zwei Funktionen:

http://upload.wikimedia.org/math/e/3...20ce9955d8.png

http://upload.wikimedia.org/math/8/0...db720a87fe.png

Zunächst sucht man nun (durch ausprobieren?) die größte Zahl i (oben dargestellt durch die Funktion q), für die gilt f(i) <= 39. i ist in unserem Fall 8. Dann ist y = 39 - f(8) = 39 - 36 = 3.
x ergibt sich aus i - y = 8 - 3 = 5.

Noch Fragen :mrgreen: ?

edit: und unter o.g. Link findet man sogar noch Pascal-Code für die Umkehrfunktion:
Delphi-Quellcode:
procedure CantorPair(    I  : Integer;
                     Var X,Y : Integer);
{ Gibt das i-te Paar (X,Y) in Diagonalabzaehlung zurueck }
var
   J : Integer;
 
   function F(Z : Integer) : Integer;
   begin
      F := Z * (Z + 1) div 2 
   end;

   function Q(Z : Integer) : Integer;
   var
      V : Integer;
   begin
      V := 0;
      while F(V) <= Z do
         V := V + 1;
      Q := V - 1
   end;

begin
   J := Q(I);
   Y := I - F(J);
   X := J - Y;
end;

Jonelmeier 15. Mai 2010 12:03

Re: Zwei Werte [0..16] in einem Integer festhalten
 
@himitsu: Vielen Dank für deine vielen schnellen Ideen!

Ich habe es jetzt auf die mathematische Weise gelöst:

Setzen:
Delphi-Quellcode:
MyInt := X * Max(MAX_X, MAX_Y) + Y;
Auslesen:
Delphi-Quellcode:
X := MyInt div Max(MAX_X, MAX_Y);
Y := MyInt mod Max(MAX_X, MAX_Y);
@Meflin: Nein, keine weiteren Fragen :wink:

Danke nochmal!

himitsu 15. Mai 2010 12:46

Re: Zwei Werte [0..16] in einem Integer festhalten
 
Es müßte wohl mehr so aussehn:
MAX_Y+1 ist ja der kleinste Wert, in dessen Vielfachen X liegen muß, so daß Y noch reinpaßt.

Setzen:
Delphi-Quellcode:
MyInt := X * (MAX_Y + 1) + Y;
Auslesen:
Delphi-Quellcode:
X := MyInt div (MAX_Y + 1);
Y := MyInt mod (MAX_Y + 1);

und falls MIN_Y auch negativ sein kann:
Setzen:
Delphi-Quellcode:
MyInt := X * (Max(MAX_Y, Abs(MIN_Y)) + 1) + Y;
Auslesen:
Delphi-Quellcode:
X := MyInt div (Max(MAX_Y, Abs(MIN_Y)) + 1);
Y := MyInt mod (Max(MAX_Y, Abs(MIN_Y)) + 1);

divBy0 15. Mai 2010 13:18

Re: Zwei Werte [0..16] in einem Integer festhalten
 
Du könntest die beiden Werten auf jeweils im High- und Low-Word speichern. 1..16 könntest du sogar 4 mal in einem Integer unterbringen, wenn ich dich nicht falsch verstanden hab.

himitsu 15. Mai 2010 13:38

Re: Zwei Werte [0..16] in einem Integer festhalten
 
@divBy0: 1..16 paßt sogar bis zu 8 Mal in einen Interger rein.

bzw. ein Integer (4-Byte) läßt sich mit 8 Hexadezimalstellen (Base16) darstellen.

hathor 15. Mai 2010 13:52

Re: Zwei Werte [0..16] in einem Integer festhalten
 
So kleine Werte lassen sich in einem einzigen Byte speichern:
1..16 (0..15) = 1 Nibble
2 Nibble = 1 Byte


Weil man mit Integern rechnet, kann man gut damit umgehen:

var
numberByte: integer;
highNibble,lowNibble: integer;

(Byte:=16*highNibble + lowNibble;)
numberByte:=16*highNibble + lowNibble;

highNibble:=numberByte div 16;
lowNibble:=numberByte mod 16;


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:48 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz