2012-05-09 21 views
6

Pracuję nad przenośną biblioteką klasy w C# i chcę nieco przekonwertować double na long. Najprostszym rozwiązaniem tego problemu byłoby użycie metody BitConverter.DoubleToInt64Bits, ale niestety ta metoda nie jest dostępna w podzbiorze biblioteki przenośnej biblioteki .NET..NET Biblioteka przenośna brakująca BitConverter.DoubleToInt64Bits, wymiana bardzo powolna

Jako alternatywę I mają pochodzić z następującym „two-pass” bitowej konwersji:

var result = BitConverter.ToInt64(BitConverter.GetBytes(x), 0); 

Moje testy pokazują, że wyrażenie to konsekwentnie daje ten sam wynik jak DoubleToInt64Bits. Jednak moje testy porównawcze pokazują również, że ta alternatywna formuła jest około cztery razy wolniejsza niż DoubleToInt64Bits po wdrożeniu w pełnej aplikacji .NET Framework.

Używając tylko podzestawu Biblioteki przenośnej, czy możliwe jest zastąpienie DoubleToInt64Bits szybszym od powyższego?

Odpowiedz

5

Jak na temat korzystania z unii?

[StructLayout(LayoutKind.Explicit)] 
public struct DoubleLongUnion 
{ 
    [FieldOffset(0)] 
    public double Double; 

    [FieldOffset(0)] 
    public long Long; 
} 

public static long DoubleToInt64Bits(double value) 
{ 
    var union = new DoubleLongUnion {Double = value}; 
    return union.Long; 
} 
+1

Świetne, co za sprytne rozwiązanie, wielkie dzięki Omer! Twoje rozwiązanie jest wolniejsze niż pełna metoda 'DoubleToInt64Bits', ale jest ponad dwa razy szybsze niż moje rozwiązanie" dwuprzebiegowe ". Przez chwilę obawiałem się, że to nie zadziała w bibliotece przenośnej, ponieważ nie ma wskazania na MSDN, że podzbiór Portable Library obsługuje atrybut [FieldOffset] (http://msdn.microsoft.com/en- us/library/system.runtime.interopservices.fieldoffsetattribute.aspx). Jednak implementacja działa, więc wydaje się, że jest to tylko niedopatrzenie w dokumentacji MSDN. –

+1

Dodatkową korzyścią z twojego rozwiązania jest to, że mogę łatwo dodać pole 'ulong ULong' do struktury 'Union' i analogicznie zaimplementować metodę' DoubleToUInt64Bits' zwracającą wartość 'ulong'. Ta elastyczność jest bardzo cenna :-) –

+0

Cieszę się, że mogłem pomóc :-) –

3

Jeśli jesteś w stanie banderą Twój zespół jako unsafe następnie można po prostu podnieść realizację DoubleToInt64Bits do własnej biblioteki:

public static unsafe long DoubleToInt64Bits(double value) 
{ 
    return *(((long*) &value)); 
} 
+0

Dzięki za sugestię! Zrobiłem szybki test porównawczy twojej metody i wydaje mi się, że jest tak szybki jak metoda "DoubleToInt64Bits". Niestety, ponieważ jest to biblioteka przenośna (potencjalnie przeznaczona również dla aplikacji Silverlight, WP7 i Metro), "niebezpieczne" nie jest opcją. –

+0

Oczywiście twoja metoda musi być tak szybka jak "DoubleToInt64Bits". Za pierwszym razem przeczytałem twoją odpowiedź zbyt szybko i tęskniłem za tym, że w ten sposób zaimplementowano "DoubleToInt64Bits" :-) Przepraszam za moje zamieszanie. –

Powiązane problemy