Laden...

Aus einer GUID mehrere GUIDs erzeugen

Erstellt von wollmich vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.074 Views
wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren
Aus einer GUID mehrere GUIDs erzeugen

Guten Tag,

habe ein ganz kurze Frage:
Bei einem Zufallsgenerator kann ich das Seed setzen und so immer wieder die gleichen Zufallszahlen erzeugen.

Nun bräuchte ich so etwas für GUIDs. Das heist ich habe eine Anfangs GUID und will damit zum Beispiel 100 neue GUIDs erstellen. Ist das möglich? Im einfachsten Fall könnte ich die GUID immer um 1 erhöhen. Gibt aber sicher bessere Lösungen.

Gruss Wollmich

458 Beiträge seit 2007
vor 13 Jahren

Was willst du denn damit erreichen, eine Guid "aus einer Guid" zu generieren?
Erzeuge einfach eine neue Guid und gut is.

be the hammer, not the nail!

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Danke für die Antwort.

Ich brauche zum Beispiel 1000 GUIDs und möchte aber nur eine oder die erste Abspeichern. Die anderen 999 muss ich immer wieder GLEICH erzeugen (berechnen) können.
Analogie zu System.Random. Hier speichere ich auch nicht 10000 doubles ab, wenn ich sie immer wieder erzeugen kann, sofern ich das Random Seed kenne.

Ich hoffe es ist nun klarer.

Gruss Wollmich

1.457 Beiträge seit 2004
vor 13 Jahren

Hallo wollmich,

Nein, es ist leider nicht klarer.

Was willst du denn damit erreichen?

System.Random und GUID sind völlig unterschiedliche Dinge.

458 Beiträge seit 2007
vor 13 Jahren

Hallo,

du moechtest aus einer Guid 99 andere berechnen koennen, die immer gleich bleiben sollen, richtig?
Ich halte Guids nicht dafuer geeignet.

be the hammer, not the nail!

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

du moechtest aus einer Guid 99 andere berechnen koennen, die immer gleich bleiben sollen, richtig? Ja genau (99 ist nur ein Besipiel, könnten auh viel mehr sein).

Man könnte sich auch etwas vorstellen wie eine Struktur mit GUID (16 Bytes) und INT32 (4 Bytes). Bei erzeugen der 99 anderen IDs wird die INT32 in der Struktur einfach hochgezählt und jedes mal eine MD5 Chechsumme (16 Bytes) berechnet, welche als Input für die GUID gebraucht wird.

Es sollte möglich sein mit einer weltweit eindeutigen ID auf mehreren PC eine Sequenz von (zum Beispiel 99) neuen (immer noch eindeutigen) zu berechnen. Das Resultat muss überall gleich sein für einen gleichen Startwert.

Gruss Wollmich

1.457 Beiträge seit 2004
vor 13 Jahren

Genau dafür sind GUIDs nicht gedacht. Mit einer Kombination kannst du es womöglich hinbekommen eine Sequenz zu erzeugen, aber meine Frage - warum und wozu das benötigst hast du noch nicht beantwortet. Vielleicht gibt es ja auch andere Möglichkeiten.

Gelöschter Account
vor 13 Jahren

Es sollte möglich sein mit einer weltweit eindeutigen ID

int eindeutigeId = 0;

auf mehreren PC eine Sequenz von (zum Beispiel 99) neuen (immer noch eindeutigen) zu berechnen


for(int i = 1; i <= 99; i++)
{
eindeutigeIdListe.Add(eindeutigeId + i);
}

oder geht es hierbei etwa um COM guids?

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Wozu daas ganze:

Habe ein System für automatische Differentiation, welches für Unsicherheitsberechnung eingesetzt wird, entwickelt.
Siehe: http://en.wikipedia.org/wiki/Metas.UncLib
und http://www.metas.ch/unclib

Machen wir ein einfaches Beispiel (lineare Fortpflanzung):
Es gibt den Eingang A mit dem Wert 3 und der Unsicherheit 0.3.
Und es gibt den Eingang B mit dem Wert 4 und der Unsicherheit 0.4.

Nun wird der Ausgang C berechnet C = sqrt(AA + BB). Nun möchte man den Wert von C wissen und die Unsichheit davon.

Beim Erzeugen von der Eingangsgrössen A und B wird im Moment je eine GUID vergeben damit diese eine eindeutige ID haben.
Im Result C steht der Wert (als double), und die ID von A und B (als GUID), sowie die Ableitund dC/DA und dC/dB (als double).
GUIDs werden gebraucht damit die IDs eindeutig sind, wenn zum Beispiel auf mehrenen PC geabeitet wird oder das Program neugestartet wird. Ein einfache int32 ID die einfach bei 0 startet reicht hier nicht aus.

Nun zum Problem:
Im Normalfall wird bei jeden Erzeugen einer Eingangsgrösse (wie A oder B oben) eine neue GUID vergeben. Was auch so sein muss.
Sonderfall 1: Zwischendurch sollte es möglich sein eine Eingängsgrösse mit einer bestimmten ID nochmals zu erzeugen. Auch kein Problem (man kennt die ID und erzeugt keine neue).
Sonderfall 2: Man möchte zum Beispiel 100 neue Eingangsgrössen erzeugen, kennt aber nur die Start ID. Hier liegt das oben beschriebene Problem.

Gruss Wollmich

1.378 Beiträge seit 2006
vor 13 Jahren

Ich würd mir in dem Fall eher einen künstlichen Schlüssel einfallen lassen, der sich aus den Werten oder aus der Berechnung selbst zusammensetzt. Diesen kann man dann auch wieder auflösen und den ursprünglichen Zustand daraus herstellen.

Im einfachsten Fall eine string Verkettung der relevanten Parameter? Aber für Guid sehe ich hier keine Verwendung. Vor allem nicht wenn es wirklich eindeutig sein soll und ableitbar.

Lg XXX

Gelöschter Account
vor 13 Jahren

Hier sind Guids meiner ansicht nach nciht geeignet. Du willst, das die ID sich an den Werten orientieren, richtig? wenn ja, dann generiere die ID anhand dieser Werte. Das kann auch ein einfacher string sein, der die werte Kommasepariert aneinanderhängt.

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Ok ich muss etwas weiter ausholen.

Es gibt die Klasse LinProp.UncNumber mit folgenden Feldern:

double value;
guid[] id;
double[] jacobi;

Nun das Beispiel von oben c = sqrt(aa + bb)

  1. a = UncNumber(3, 0.3)
a.value = 3
a.id[0] = 0 <-- automatisch erzeugte GUID
a.jacobi[0] = 0.3
  1. b = UncNumber(4, 0.4)
a.value = 4
b.id[0] = 1 <-- automatisch erzeugte GUID
b.jacobi[0] = 0.4
  1. a2 = a*a
a2.value = 9
a2.id[0] = 0 <-- ich hänge von 'a' ab
a2.jacobi[0] = 1.8
  1. b2 = b*b
b2.value = 16
b2.id[0] = 1 <-- ich hänge von 'b' ab
b2.jacobi[0] = 3.2
  1. c2 = a2 + b2
a2.value = 25
a2.id[0] = 0 <-- ich hänge von 'a'
a2.jacobi[0] = 1.8
b2.id[1] = 1 <-- und 'b' ab
b2.jacobi[1] = 3.2
  1. c =sqrt(c2)
a2.value = 5
a2.id[0] = 0 <-- ich hänge von 'a'
a2.jacobi[0] = 0.18
b2.id[1] = 1 <-- und 'b' ab
b2.jacobi[1] = 0.32

Nun wieder zum Problem:
Es muss möglich sein, eine Eingängsgrösse mit einer bestimmten ID nochmals zu erzeugen.
Zum Beispiel mit LinProp.UncNumber(double value, double unc, guid id). Das ist kein Problem.
Es sollte aber auch möglich sein, ein Array von Eingangsgrössen zu erzeugen mit bekannten IDs. Man könnte sich den Constructor von vorhin in einem Loop vorstellen oder
LinProp.UncNumber(double[] value, double[] unc, guid[] id), wäre auch kein Problem. Ich bräuchte nun aber so etwas:
LinProp.UncNumber(double[] value, double[] unc, guid id) und hier liegt das Problem. Wie generiere ich aus einer GUID 100 andere?

Gruss Wollmich

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Man könnte sie soetwas vorstellen:

        public static Guid[] GuidGenerator(Guid start, int n)
        {
            Guid[] ids = new Guid[n];
            for (int i = 0; i < n; i++)
            {
                byte[] data = new byte[16 + 4];
                start.ToByteArray().CopyTo(data, 0);
                BitConverter.GetBytes(i).CopyTo(data, 16);
                MD5 md5hasher = MD5.Create();
                byte[] hash = md5hasher.ComputeHash(data);
                ids[i] = new Guid(hash);
            }
            return ids;
        }

Gruss Wollmich

Gelöschter Account
vor 13 Jahren

Wie bereits mehrfach erwähnt bist du mit Guid hier auf dem Holzweg.

Ich sehe immer noch nicht, inwieweit die Stringbasierte Identifikation hier Konflikte verursachen könnte.

Btw: wenn Werte zusammengehören, dann übergebe sie zusammen in einer Struktur oder Klasse. also sowas: "UncNumber(double[] value, double[] unc, guid[] id)" ist echt unschön.

Hierfür gibt es ab .net 4.0 die praktische Tuple<T1,T2,T3> Klasse. Oder du machst eine eigene Struktur.

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Zum Btw (structs):
Das ist klar. Wollte nur den Beschrieb meines Problemes nicht unnötig verlängern.
Auch die LinProp.UncNumber Klasse sieht im Code so aus:


public class UncNumber
{
    double value;
    DependsOn[] dependencies;
}
public struct DependsOn
{
    guid id;
    double jacobi;
}

Nun warum GUIDs als IDs und nicht irgendwelche Strings:
1: Wenn ich mehre Ids aus einer StartId erzeugen möchte, könnte ich die StartId + den Zähler in einem neuen String speichern. 😃
2. Was für einen String erzeuge ich aber, wenn der User nichts spezifiziert und die ID weltweit eindeutig sein sollte? Dies ist der Standardfall (99%).
3. Bei jeder Grundoperation (+ - * / usw) muss ich die Kettenregel anwenden und nachschauen von welchen Eingängen ich abhänge. Also Ids vergleichen. GUIDs lassen sich schneller vergleichen als Strings 😦 Man könnte natürlich eine Lockup Table führen (interne ID als int32, externe ID als string) und immer nur die Internen IDs vergleichen.

Gruss Wollmich

Gelöschter Account
vor 13 Jahren

@2: Du arbeitest mit absoluten Zahlen. Also was meinst du mit "nichts"?
@3: Wenn es um Performance geht, so kannst du immer noch den Hashcode des Strings cachen (String und Hashcode in einer Klasse wrappen z.b.) und in erster Instanz immer mit dem Hashcode vergleichen und erst wenn der Hashcode zufällig gleich ist, dann einen echten Stringcompare durchführen.

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

@2: Mit nichts meine ich nichts 😉
Beispiel 1 der User gibt keine ID vor:

var x1 = new UncNumber(0, 1);
var x2 = new UncNumber(0, 1);
var x3 = new UncNumber(0, 1);

x1, x2 und x3 haben alle den gleichen Wert und die gleiche Unsicherheit, sie sollen aber alle eine andere eindeutige ID bekommen, da sie nicht korreliert sind. (Evtl. werden sie auf verschieden PCs erzeugt usw, darum GUID bis jetzt).

Beispiel 2 der User gibt eine ID vor:

string id = "Ich habe eine StringID";
var y1 = new UncNumber(0, 1, id + "1");
var y2 = new UncNumber(0, 1, id + "2");
var y3 = new UncNumber(0, 1, id + "3");

@3: Ja das ist nicht wirklich ein Problem. Entweder Hashes vergleichen, oder eine LoockUp Table mit interner und externer ID.

--- edit ---
Die ID hat nichts mit dem Wert (double) und der Unsicherheit (double) zu tun.

Gruss Wollmich

Gelöschter Account
vor 13 Jahren

ok aber warum willst du dann die selben id´s auf unterschiedlichen ps´s erzeugen lassen? Denn genau das soll ja Guid nicht machen.

L
416 Beiträge seit 2008
vor 13 Jahren

Warum speicherst du die Guids nicht einfach zu den Werten ab? Und ja wie Jack meint warum brauchst du die gleichen? Die dienen doch nur zur Abbildung deiner Relationen wenn ich das richtig verstanden habe.

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Hey JAck30lena, danke das du solange mit diskutierst 😃

Ich muss noch etwas weiter ausholen.
Angenommen man hat zum Beispiel irgendwelche Kalibrationsstandards (Eingangsgrössen) mit einer Werte Tabelle und jeder Wert hat eine Unsicherheit.

Nun möchte man mit diesem Standard als Eingangsgrösse für Berechnungen brauchen.
Wird nun auf zwei PC die gleiche Berechnung durchgeführt, muss das Resultat voll zueinander korrelieren, also von den gleichen IDs abhängen.

So weit so gut, ist auch noch kein Problem. Den Standard könnte man als UncNumber Array abspeichern. Jeder Wert hätte eine Unsicherheit und eine ID. So hat ein einziger Standard problemlos 1000 IDs. Schöner wäre nur eine ID und die restlichen erzeugen.

Nun gibt es aber noch spezielle Standards (Einflussgrössen) die sehr viele (bis zu 10000) Werte und Unsicherheiten haben, wobei der Wert immer 0 und die Unsichheit immer 1 ist. Hier macht es keinen Sinn den Wert und die Unsicherheit zu merken, da immer 0 resp. 1). Hier müsste man sich nur ein Array von IDs merken. Auch hier wäre es schöner nur eine ID zu merken und die restlichen erzeugen.

Gruss Wollmich

Gelöschter Account
vor 13 Jahren

Ok. Dann schlage ich vor du verwendest einen Compound Key. Einen Präfix (eindeutig, kann auch guid sein) und einen laufenden wert (Zählvariable z.b.). Zusätzlich könntest du noch die Werte mit anhängen. So könntest du aus dem CompundKey dein Objekt herausrechnen.

Um das ganze perfomant gestalten zu können musst du das recht gut kapseln und einen mehrstufigen Vergleich durchführen.

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Noch etwas:

Ich mache nochmals kurz den Vergleich zu System.Random()
Man kann Unsicherheiten auch mit Hilfe von Monte-Carlo ausrechnen.

  • Die Eingänge mehrmals würfeln.
  • Berechnung durchführen.
  • Resultat analysieren.

Hier habe ich zwei Möglichkeiten meine Standards (Einflusgrössen abzuspeichern):

  1. Alle Zahlen würfeln und speichern (bis zu 10000 x 1000000 für das Beispiel weiter oben).
  2. Den Zustand des Random.Generators speichern (zum Beipiel das seed). Wäre natürlich nicht System.Random mit 32bit seed sondern ein anderer Random generator mit 128bit seed. So reicht eine ID, um die gleichen Zahlen nochmals zu würfeln.

Gruss Wollmich

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Ok. Dann schlage ich vor du verwendest einen Compound Key. Einen Präfix (eindeutig, kann auch guid sein) und einen laufenden wert (Zählvariable z.b.). Zusätzlich könntest du noch die Werte mit anhängen. So könntest du aus dem CompundKey dein Objekt herausrechnen.

Das würde so etwas geben:

public class UncNumber
{
    double value;
    DependsOn[] dependencies;
}
public struct DependsOn
{
    CompoundKey id;
    double jacobi;
}
public struct CompoundKey
{
    guid p;
    int c; // counter
}

Nun ist meine ID aber 20 Bytes und nicht nur 16 Bytes. Schön wäre ein System bei dem ich mit 16 Bytes auskommen würde.

Gruss Wollmich

R
103 Beiträge seit 2009
vor 13 Jahren

Also Ich fand Deinen Vorschlag mit einer Guid und dem Int32 als Zähler und anschliessendenm Md5 ganz gut, nur würde ich den Zählerwert nicht auf die Guid aufaddieren, sondern den md5 string aus beiden Werten (also 20 bytes) nehmen.

Auf meinem guten alten Windows NT 4 war das immer so, dass sich die Guid aus der Mac Addresse + irgendwas anderes statisches + Zähler zusammensetzte, mittlerweile scheint Microsoft sich da was besseres überlegt zu haben (MD5? 😉).

wollmich Themenstarter:in
178 Beiträge seit 2008
vor 13 Jahren

Also Ich fand Deinen Vorschlag mit einer Guid und dem Int32 als Zähler und anschliessendenm Md5 ganz gut, nur würde ich den Zählerwert nicht auf die Guid aufaddieren, sondern den md5 string aus beiden Werten (also 20 bytes) nehmen.

Genau (nicht addieren sondern zusammenhängen) habe ich weiter oben unter 'Guid[] GuidGenerator(Guid start, int n)' vorgeschlagen.

Gruss Wollmich

R
103 Beiträge seit 2009
vor 13 Jahren

Oops sorry, Thread nicht zu Ende gelesen und gleich gepostet ..
Genau das meinte ich.
MD5 gilt zwar nicht (mehr) als Kollisionssicher, aber ich glaube für diesen Zweck kann man das bequem ignorieren.