2012-05-09 10 views
6

Estoy desarrollando una biblioteca de clases portátil en C# y quiero convertir un double a long bit. La solución más directa a este problema sería utilizar el método BitConverter.DoubleToInt64Bits, pero lamentablemente este método no está disponible en el subconjunto Biblioteca portátil de la biblioteca de clases .NET..NET biblioteca portátil que falta BitConverter.DoubleToInt64Bits, reemplazo muy lento

Como alternativa He llegado con la siguiente conversión bit "de dos pasadas":

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

Mis pruebas muestran que esta expresión consistentemente produce el mismo resultado que DoubleToInt64Bits. Sin embargo, mis pruebas comparativas también muestran que esta formulación alternativa es aproximadamente cuatro veces más lenta que DoubleToInt64Bits cuando se implementa en una aplicación .NET Framework completa.

Utilizando solo el subconjunto Biblioteca portátil, ¿es posible implementar un reemplazo de DoubleToInt64Bits que sea más rápido que mi formulación anterior?

Respuesta

5

¿Cómo sobre el uso de un sindicato?

[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

Genial, qué solución tan inteligente, muchas gracias Omer! Su solución es más lenta que el método de marco completo 'DoubleToInt64Bits', pero más del doble de rápido que mi solución de" dos pasos ". Durante un tiempo me preocupó un poco que esto no funcionara en una biblioteca portátil, ya que no hay ninguna indicación en MSDN de que el subconjunto de la Biblioteca portátil sea compatible con el atributo [FieldOffset] (http://msdn.microsoft.com/en- us/library/system.runtime.interopservices.fieldoffsetattribute.aspx). Sin embargo, la implementación funciona, por lo que solo parece ser un descuido en la documentación de MSDN. –

+1

Un beneficio adicional con su solución es que puedo agregar fácilmente un campo 'ulong ULong' a la estructura' Union', e implementar análogamente un método 'DoubleToUInt64Bits' que devuelve un valor' ulong'. Esta flexibilidad es muy apreciada :-) –

+0

Me alegro de haber podido ayudar :-) –

3

Si usted es capaz de bandera de su ensamblaje en calidad unsafe entonces usted podría simplemente levantar la implementación DoubleToInt64Bits en su propia biblioteca:

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

¡Gracias por la sugerencia! Hice una prueba de referencia rápida de su método, y parece ser aproximadamente tan rápido como el método 'DoubleToInt64Bits'. Desafortunadamente, dado que es una biblioteca portátil (potencialmente dirigida también a aplicaciones Silverlight, WP7 y Metro), 'inseguro' no es una opción. –

+0

Por supuesto, su método debe ser tan rápido como 'DoubleToInt64Bits'. Leí tu respuesta demasiado rápido la primera vez y me perdí la parte de que esta es la forma en que se implementa 'DoubleToInt64Bits' :-) Perdón por mi confusión. –