2012-05-09 8 views
6

Sto sviluppando una libreria di classi portatile in C# e voglio convertire in bit un double in un long. La soluzione più semplice a questo problema sarebbe utilizzare il metodo BitConverter.DoubleToInt64Bits, ma sfortunatamente questo metodo non è disponibile nel sottoinsieme Libreria portatile della libreria di classi .NET.Libreria portatile .NET mancante BitConverter.DoubleToInt64Bits, sostituzione molto lenta

Come alternativa ho fornito con la seguente conversione bit "two-pass":

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

miei esperimenti indicano che questa espressione produce costantemente lo stesso risultato DoubleToInt64Bits. Tuttavia, i miei test di benchmark mostrano anche che questa formulazione alternativa è circa quattro quattro volte più lenta di DoubleToInt64Bits se implementata in un'applicazione .NET Framework completa.

Utilizzando solo il sottoinsieme di Portable Library, è possibile implementare una sostituzione di DoubleToInt64Bits che sia più veloce della mia formulazione sopra?

risposta

5

Come sull'utilizzo di un sindacato?

[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

Grande, che soluzione intelligente, molte grazie Omer! La tua soluzione è più lenta del metodo completo 'DoubleToInt64Bits', ma più del doppio della mia soluzione" two-pass ". Per un po 'ero un po' preoccupato che ciò non funzionasse in una libreria portatile, dal momento che non c'è alcuna indicazione su MSDN che il sottoinsieme Libreria portatile supporti [l'attributo FieldOffset] (http://msdn.microsoft.com/ us/library/system.runtime.interopservices.fieldoffsetattribute.aspx). Tuttavia, l'implementazione funziona in modo che solo sembra essere una svista nella documentazione MSDN. –

+1

Un ulteriore vantaggio della soluzione è che posso facilmente aggiungere un campo 'ulong ULong' alla struttura' Union', e analogamente implementare un metodo 'DoubleToUInt64Bits' restituendo un valore' ulong'. Questa flessibilità è molto apprezzata :-) –

+0

Contento di aver potuto aiutare :-) –

3

Se siete in grado di bandiera vostra assemblea come unsafe allora si può solo sollevare l'attuazione DoubleToInt64Bits nella vostra libreria:

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

Grazie per il suggerimento! Ho fatto un rapido test di benchmark del tuo metodo, e sembra essere veloce come il metodo 'DoubleToInt64Bits'. Sfortunatamente, dato che è una libreria portatile (potenzialmente destinata anche alle applicazioni Silverlight, WP7 e Metro), 'non sicuro 'non è un'opzione. –

+0

Ovviamente, il tuo metodo è destinato ad essere veloce come 'DoubleToInt64Bits'. Ho letto la tua risposta troppo velocemente la prima volta e ho perso la parte in cui questo è il modo in cui 'DoubleToInt64Bits' è implementato :-) Scusa per la mia confusione. –