| 

.NET C# Java Javascript Exception

11
Hi,

ich habe ein kleines Umwandlungsproblem. Ich will einen ulong Wert schnell in zwei uint Werte splitten und diese anschließend wieder in einen ulong zurückwandeln. Das bekomme ich irgendwie nicht hin.
04.03.2014
roni 137 1 5
Jens Duczmal 2,6k 1 3 9
1
Ich war so frei und habe im Titel einen Tippfehler korrigiert und die Tags noch ergänzt :)
Jens Duczmal 04.03.2014
3 Antworten
10
Die Main ruft 2 Methoden auf, die das für dich erledigen.

public static void Main(string[] args)
{
ulong ul1 = ulong.MaxValue;
uint[] ui = UlongToUints(ul1);
ulong ul2 = UintsToUlong(ui[0], ui[1]);

Console.WriteLine(ul1.ToString());
Console.WriteLine(ui[0].ToString() + " " + ui[1].ToString());
Console.WriteLine(ul2.ToString());

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}

internal static uint[] UlongToUints(ulong v)
{
return new uint[] {(uint)(v & 0xFFFFFFFF), (uint)((v >> 32)&0xFFFFFFFF)};
}

internal static ulong UintsToUlong(uint highUint, uint lowUint)
{
ulong output = highUint;
output = output << 32;
output += lowUint;
return output;
}


Update -----------------------

Ich fand die Lösung von ffordermaier irgendwie toll und deshalb füge ich meiner Lösung eine komplette statische Klasse bei, mit der jeder auch seine Lösung probieren kann. Jetzt kann jeder seine Vergleichstests selbst durchführen - ich hab das zeitlich noch nicht geschafft. Vielleicht ist jemand schneller als ich...? Hier der Code:

public static class Union_Struct
{
[StructLayout(LayoutKind.Explicit)]
public struct Union
{
[FieldOffset(0)] public ulong Ulong;
[FieldOffset(0)] public uint UInt1;
[FieldOffset(4)] public uint UInt2;
}

internal static uint[] UinionUlongToUints(ulong v)
{
var union = new Union() { Ulong = v };
return new uint[] {union.UInt1, union.UInt2};
}

internal static ulong UnionUintsToUlong(uint highUint, uint lowUint)
{
var union = new Union()
{ UInt1 = highUint, UInt2 = lowUint };
return union.Ulong;;
}
}


2, Update:----------------------------------------------------

Geschwindigkeitstest

Gemessen wurde: Meine Lösung und UnionStruct-Lösung:

private static void Test()
{
ulong ul1 = ulong.MaxValue -3;
uint[] x;
ulong ul;
string s1, s2;
Stopwatch watch = new Stopwatch();
watch.Start();

int max = int.MaxValue;

for(int y = 0; y < max; y++)
{
x = Union_Struct.UinionUlongToUints(ul1);
ul = Union_Struct.UnionUintsToUlong(x[0], x[1]);
}
watch.Stop();
s1 = watch.Elapsed.ToString();

watch = new Stopwatch();
watch.Start();

for(int y = 0; y < max; y++)
{
x = UlongToUints(ul1);
ul = UintsToUlong(x[0], x[1]);
}

watch.Stop();
s2 = watch.Elapsed.ToString();

Console.WriteLine("\tTime spent:\n\n\tUnion-Struct:\t" +
s1 + "\n\tMeine Lösung:\t" + s2);
}


UnionStruct ist bis zu einem max. Schleifendurchlauf von etwa 2000 schneller. NeineLösung steigt in der Geschwindigkeit nach 2000. Hier ist das Zeitergebnis für max = int.MaxValue:


UnionStruct: 00:01:46.9201654
Meine Lösung: 00.01:18.1970954


Viel Spass damit!
04.03.2014
Falkner 795 3 9
Falkner 795 3 9
Feine Lösung. Als Rückgabetyp von UlongToUints könnte man auch Tupel<uint,uint> in Erwägung ziehen.
Matthias Hlawatsch 04.03.2014
Danke für die superschnelle Antwort. Mein Problem ist gelöst. Ich habs grad ausprobiert. Da wär ich so nicht drauf gekommen.
roni 04.03.2014
5
Ein eher unbekanntes Feature - eine Art Union Struct - kann das Problem auch sehr elegant lösen:

[StructLayout(LayoutKind.Explicit)]
public struct Union
{
[FieldOffset(0)] public ulong Ulong;
[FieldOffset(0)] public uint UInt1;
[FieldOffset(4)] public uint UInt2;
}

[Fact]
public void UnionTest()
{
var union = new Union() { Ulong = 0xFFFFFFAAEEBBBB00 };
var uint1 = union.UInt1;
var uint2 = union.UInt2;

Assert.Equal(uint1 ,0xEEBBBB00);
Assert.Equal(uint2, 0xFFFFFFAA);
}
05.03.2014
ffordermaier 8,4k 3 9
@ffordermaier: Eine Alternative zu meiner Lösung, die Beachtung verdient. Aber wie sieht das mir der Geschwindigkeit aus? Ich zumindest werde am WE mal einige Versuche damit veranstalten. Ich kannte so eine Konstruktion bisher nicht.
Falkner 05.03.2014
@Falkner: Performanceerfahrungen habe ich leider keine damit. Aber wenn Du Messungen durchführst, würde mich das Ergebnis sehr interessieren.
ffordermaier 06.03.2014
@ffordermaier: Werde ich am WE mal machen.
Falkner 06.03.2014
2
@ffordermaier: Hab meiner Lösung deine als Klasse zugefügt. Ach so, wenn jemand diese probieren will muss:

using System.Runtime.InteropServices;

eingebunden werden.
Falkner 06.03.2014
@Falkner: Hast Du mal gemessen mittlerweile?
ffordermaier 13.03.2014
@ffordermaier: Leider nein, ich bin die letzten Tage zu irgendwie garnichts gekommen. Bin bis oben hin mit Arbeit dicht gestapelt. Ich schaffe das frühestens zum nächsten WE - LEIDER!
Falkner 13.03.2014
@Falkner: Kein Stress, wann auch immer Du dazukommst. Interessant ist es allemal.
ffordermaier 14.03.2014
@ffordermaier: Ich habe meiner Lösung ein weiteres Update zugefügt und ebenfalls die Methode, mit der ich gestestet habe.

Mir scheint, beide Lösungen haben, auf die Geschwindigkeit bezogen, ihre Berechtigung. Mehrmalige Anwendung bis ca. 2000 mal sprechen für UnionStruct, und darüber hinausgehende Anwendung scheint eindeutig meine Lösung zu empfehlen. Also Anwendung nach Bedarf.

Ich werde wohl weiter mit meiner Lösung arbeiten, weil ich oft in solche Methoden direkt eingreifen muss.
Falkner 15.03.2014
2
Mit einer unsafe Variante geht das Ganze auch. Hierbei wird kein neuer Speicher alloziert (egal ob explizit für eine struct oder implizit über Shift-Operatoren), sondern die Teile des ulong direkt von seinem Speicherplatz abgegriffen.

public unsafe uint* FirstUintFromUlong(ulong* ul)
{
return (uint*)ul;
}

public unsafe uint* SecondUintFromUlong(ulong* ul)
{
uint* p = (uint*)ul;
return p + 1;
}

[Fact]
public unsafe void TestMethod()
{
var ul = 0xFFFFFFAAEEBBBB00;

var first = FirstUintFromUlong(&ul);
Assert.Equal(*first, 0xEEBBBB00);

var second = SecondUintFromUlong(&ul);
Assert.Equal(*second, 0xFFFFFFAA);
}
06.03.2014
ffordermaier 8,4k 3 9
1
@ffordermaier: Ich glaube, so umfangreich wird sehr selten ein so einfaches Thema behandelt! :-)
Falkner 06.03.2014
@Falkner: Oft sind es die einfachen Dinge, über die man viel zu selten nachdenkt, nur um dann festzustellen, wieviel Vielfalt sie doch bieten :)
ffordermaier 06.03.2014

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH